즐코

CSS / 햄버거 버튼 만들기 + 간단한 on/off switch 동작 구현 본문

HTML, CSS

CSS / 햄버거 버튼 만들기 + 간단한 on/off switch 동작 구현

YJLEE_KR 2021. 12. 27. 16:31

사이드 메뉴바의 ON-OFF SWITCH 개념 (toggle) + 아주 간단한 애니메이션 구현

 

1/ html 파일로 구조를 짜준다.

 

#1. 사용자가 관여할 수 있도록 click 기능이 필요하므로, input type="checkbox" 로 잡고 id="icon" 부여함

#2. 웹접근성을 위해 label을 지정해주고

#3. 그 label 안에 메뉴 아이콘 상의 3줄을 span으로 구성함

#4. 아이콘을 누르면 메뉴가 나오게끔 관련 박스는 div id="header"로 잡음

<body>
  <input type="checkbox" id="icon">
  <label for="icon"> 
    <span></span>
    <span></span>
    <span></span>
  </label>
  <div id="header">
  </div>
</body>

 

2/ CSS 만질 차례

 

#1. 우선 input type="checkbox"로 잡았기 때문에 체크박스 자체를 안보이게 하는 거 플러스

checked 즉, 누른 상태에도 체크박스가 안보여야 하므로 두 상태에 다 display:none을 적용시킨다.

* input[id="icon"] ->> #icon로 써도됨

- display:none; : display:none 일 경우, input 박스는 안보이지만, 숨겨져 있는것이다.

즉, 기능적으론 살아있지만(실제론 동작하고 있지만) 화면상에만 랜더링이 안된 것
* input : inline 속성이지만 width로 넓어지는 특징을 가지고 있다.

input[id="icon"]{
  display:none;
  }

input[id="icon"]:checked{
  display:none;
  }

- checked가 되어있을 때 안되어있을 때의 css를 다르게 잡을 수 있다.
  메뉴바 같은 경우 display:none; 안보였다가 check 누르면 효과, 즉 메뉴바가 등장하게 할 때 쓰임

 

#2. input과 바로 붙어있는 label, 즉 3줄이 들어갈 전체 틀을 꾸며준다.   

 

1) Adjacent Sibling combinator 인접 형제 선택자 개념을 이용한다.

   선행 태그 + 뒤에 붙어 나오는 태그 (input#icon+label)

2) 우선 label은 inline 특징을 가졌으므로, display:block으로 block화 시켜준다.

3) 전체 아이콘 크기 w60 x h40px로 잡아주고,

   해당 크기를 기준으로 안 쪽 3줄 span을 잡아줄 것이므로, position:relative를 지정해준다.

4) cursor:pointer ; 마우스 커서를 갖다대면 손가락모양으로 바뀌게 해주는 기능

input[id="icon"] + label{
  display:block;
  width:60px;
  height:40px;
  cursor:pointer;
  position:relative;
  margin-top:10px;
  }

 

 

#3. label 안의 3줄 즉 span들을 꾸며줘야 한다.

 

1) 3줄이 열배치가 되야하므로 display:block으로 block속성 주기

2) width는 label안에 딱 맞추기 위해서 width:100% 지정하고 height는 원하는대로..우선은 height:5px

3) 둥그런 엣지를 위해 border-radius:30px; 주고

4) 부모 element인 label안에서 위치를 잡게끔 position:absolute;

5) transition: all 0.35s; 이제 애니메이션 효과를 줄 건데, 그 효과의 속도를 조절시켜주는 기능

6) z-index:2 사이드메뉴가 등장했을 때도 항상 위에 존재해야하기때문에 넣어준다.

input[id="icon"] + label > span{
  display:block;
  width:100%;
  height:5px;
  border-radius:30px;
  background:black;
  position:absolute;
  transition: all 0.35s;
  z-index:2;
}

 

#4. 3줄을 간격 동일하게 맞춰준다. 

 

1) 이 때, span에 각 id를 부여하기보다는, CSS 상에서 숫자로 지정해줄수가 있다.

tag:nth-child($) -> span:nth-child(1) (2) (3)....

2) 각 span들을 지정해주고, 위치를 잡아준다. 

    - 첫번째 줄은 top에서 0px / 두번째 줄은 가운데니까 top:50% / 세번째 줄은 bottom에서 0px

      근데 이렇게 할 경우, 아래 그림처럼 두번째 줄이 가운데로 가지 않는다...

 

3) 이 때, transform:translateY(-50%)를 넣어주면, 자기 height의 50%만큼만 위로 올라간다. 

(Y축으로 이동한다는 뜻 / 웹페이지 스크롤 내리는 방향이 (+)이므로 Y축의 (-) 음수방향은 반대인 위로 올라가는 방향)

input[id="icon"] + label > span:nth-child(2){
top:50%;
}
 
input[id="icon"] + label > span:nth-child(2){
top:50%;
transform:translateY(-50%);
}
input[id="icon"] + label > span:nth-child(1){
top:0px;
}

input[id="icon"] + label > span:nth-child(2){
top:50%;
transform:translateY(-50%);
}

input[id="icon"] + label > span:nth-child(3){
bottom:0px;
}

 

#5. 이제 checked, 즉 사용자가 클릭했을 때 어떻게 바뀔지를 나타내주는 구간을 쓸 차례다.

 

input[id="icon"]:checked + label > span:nth-child(1) (2) (3) ... 범위를 잡아주고, 

1) 첫번째 줄은, 50% 내려오고 + 중간으로 살짝 내려 조정하고 + 45도 아래로 틀기

2) 두번째 줄은 사라지게 하기

3) 세번째 줄은, 50% 올라와서 + 중간으로 살짝 올려 조정하고 + 45도 위로 틀기

input[id="icon"]:checked + label > span:nth-child(1){
  top:50%;
  transform:translateY(-50%) rotate(45deg)
}

input[id="icon"]:checked + label > span:nth-child(2){
  opacity:0;
}

input[id="icon"]:checked + label > span:nth-child(3){
  bottom:50%;
  transform:translateY(50%) rotate(-45deg)
}

 

#6. 메뉴 3줄 아이콘은 끝났고, 아이콘을 누르면 나올 사이드메뉴를 꾸밀 차례

 

#icon + label + #header{} 

 

1) 우선 아이콘과 사이드메뉴는 웹사이트 스크롤을 내려도 존재해야하므로 position:fixed;로 고정시킨다.

2) 사이드 메뉴 크기 및 색상 구성하고 컨텐츠 여백을 위해 padding 값 + box-sizing

3) left:-300px; 는 안보이는 상태가 default니까 안보이게 왼쪽으로 숨겨두기 위해 넣음

4) z-index:1 ; 사이드바가 나와도 메뉴 아이콘을 덮지 않게끔

5) 메뉴 나오는 속도 transition: all 0.5s로 느리게 바꿈

 

#7. 아이콘 눌렀을 때 사이드메뉴가 숨어있다가(default) 나오게끔(checked) 

#icon:checked + label + #header{} 

left:0px 로 화면상에 나오게끔 구성

#icon + label + #header{
  position:fixed;
  width:300px;
  height:100%;
  background:#333;
  top:0px;
  padding:60px 25px 25px 25px;
  box-sizing:border-box;
  left:-300px;
  z-index:1;
  transition: all 0.5s;
}

#icon:checked + label + #header{
  left:0px;
}
Comments