CSS&JS/👀Study and Copy

WDS,OT - Magic CSS Indicator

arancia_ 2022. 8. 9. 15:20

 

 

 

HTML,JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Can I Create Online Tutorial’s Magic CSS Indicator?</title>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,500,0,0" />
    <link rel="stylesheet" type="text/css" href="./css/reset.css"/>
    <link rel="stylesheet" type="text/css" href="./css/indicator.css"/>
</head>
<body>
    <div id="gnb-wrap">
        <div id="gnb-indicator"></div>
        <ul id="gnb">
            <li>
                <button class="gnb-btn"><span class="gnb-ic material-symbols-outlined">home</span></button>
                <div class="gnb-txt">Home</div>
            </li>
            <li>
                <button class="gnb-btn"><span class="gnb-ic material-symbols-outlined">person</span></button>
                <div class="gnb-txt">Person</div>
            </li>
            <li class="on">
                <button class="gnb-btn"><span class="material-symbols-outlined">forum</span></button>
                <div class="gnb-txt">Comment</div>
            </li>
            <li>
                <button class="gnb-btn"><span class="gnb-ic material-symbols-outlined">photo_camera</span></button>
                <div class="gnb-txt">Photo</div>
            </li>
            <li>
                <button class="gnb-btn"><span class="gnb-ic material-symbols-outlined">settings</span></button>
                <div class="gnb-txt">Settings</div>
            </li>
        </ul><!-- gnb -->
    </div><!-- gnb-wrap -->
 
<!-- [스크립트] -->
<script>
    const $gnb = document.getElementById('gnb');
    const $indicator = document.getElementById('gnb-indicator');
    const INFO = {
        size:70, pad:10, gap:5 
    }
 
    $gnb.addEventListener('click',on_click_gnb);
 
    function on_click_gnb(e){
        const target = e.target;
        if(!target.classList.contains('gnb-btn')){return;}
        
        const $targetLi = target.parentElement;
        const $$sibLi = Array.from($gnb.children);
        const IDX = Array.prototype.indexOf.call($$sibLi, $targetLi);
 
        $$sibLi.forEach($sib => {
            $sib.classList.toggle('on',$sib == $targetLi);
        });
 
        const {size,pad,gap} = INFO;
        const posX = `calc((${size}px * ${IDX}) + (${pad}px + ${gap}px * ${IDX}))`;
        console.log(posX);
        $indicator.style.setProperty('transform',`translateX(${posX})`);
    }//on_click_gnb
</script>
</body>
</html>
cs

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
@charset "utf-8";
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@500;600&display=swap');
:root{
    --sans-serif:'Poppins';
    --black:#232227;
    --white:#fefefe;
    --green:#2cf8b7;
}
*{margin:0;padding:0;box-sizing:border-box;}
li{list-style-type:none;}
button{cursor:pointer;}
 
html,body{
    background:var(--black);
    font-family:var(--sans-serif); color:var(--black);
}
 
body{
    display:flex;flex-flow:column nowrap;
    justify-content:center; align-items:center;
    min-height:100vh;
}
 
#gnb-wrap{
    --size:70px;
    --padding:10px;
    --gap:5px;
    position:relative;
    height:var(--size);
    padding:0 var(--padding);
    background:var(--white);
    border-radius:1rem;
}
 
#gnb{
    display:flex;flex-flow:row nowrap;
    justify-content:center;
    gap:var(--gap);
    position:relative;
    width:100%; height:100%;
    text-align:center;}
 
#gnb li{
    /* outline:1px solid red; */
    position:relative;width:var(--size);}
 
.gnb-btn{ 
    /* outline:1px solid red; */
    height:100%; aspect-ratio:1/1;
    border:none;
    background:transparent;
    transition:transform .2s .2s;}
 
    .gnb-btn span{pointer-events:none;}
 
    /* on */
    .on .gnb-btn{transform:translateY(-40%);}
 
.gnb-txt{
    position:absolute;
    top:100%; left:0;
    width:100%;
    font-size:11px;
    opacity:0;
    transition:all .3s .3s;
    pointer-events:none;}
 
    /* .on */
    .on .gnb-txt{transform:translateY(-150%); opacity:1;}
 
/* INDICATOR */
#gnb-indicator{
    position:absolute;
    width:70px; aspect-ratio:1/1;
    top:-30px; left:0; transform:translateX(calc(
        (var(--size) * 2) + 
        (var(--padding) + var(--gap) * 2)
    ));
    border:5px solid var(--black);
    border-radius:50%;
    background:var(--green);
    transition:transform .3s;
    pointer-events:none;}
 
    #gnb-indicator::before,
    #gnb-indicator::after{
        --pos:-22px;
        content:'';display:block;position:absolute;
        top:41%;
        width:20px; aspect-ratio:1/1;
        background:transparent;
        
    }
 
    #gnb-indicator::before{
        left:var(--pos);
        border-top-right-radius:20px;
        box-shadow:1px -10px 0 0 var(--black);
    }
 
    #gnb-indicator::after{
        right:var(--pos);
        border-top-left-radius:20px;
        box-shadow:-1px -10px 0 0 var(--black);
    }
cs