안녕하세요

06월02일 13일차 - 단일 메뉴, 다단메뉴 애니메이션 구현. 애니메이션은 중간단계가 필요합니다. 본문

프론트엔드 국비교육

06월02일 13일차 - 단일 메뉴, 다단메뉴 애니메이션 구현. 애니메이션은 중간단계가 필요합니다.

sakuraop 2022. 6. 2. 16:51

[다단메뉴를 구현하는 방법을 학습했습니다.]

tag안에 무수히 많은 tag들이 들어가기 때문에 position과 hover를 어디에 주어야 할 지 파악하는 것이 어렵습니다. 

 

[수업을 마치고 개인적으로 다단 메뉴 안의 다단 메뉴를 구현해보았습니다.]

하나의 큰 다단메뉴는 height를 조절하여 애니메이션을 적용 할 수 있지만,

다단메뉴 안의 이중 다단 메뉴를 구현하기 위해서는 display: none;이 꼭 필요하기에 애니메이션을 적용할 수 없었습니다.


shortcut : 대괄호 안에 내용을 입력할 수 있습니다.
ul>li*7{BOX0$} 


외부 스타일 시트(External style sheet) 모듈화
외부 스타일 시트는 모듈화의 개념입니다. css 파일을 불러와 스타일을 적용시킵니다.

내부 스타일 시트(Internal style sheet)

내부 스타일 시트란 style 태그를 이용하여 해당 html 문서에 스타일을 적용시키는 것입니다.

인라인 스타일(Inline style)

인라인 스타일이란 html 요소 내부에서 style 속성을 사용하여 CSS 스타일을 적용하는 방법입니다.

      

인라인 스타일(Inline style)이 외부/내부 스타일 보다 우선합니다.
javascript의 적용범위는 인라인 스타일(Inline style)이므로 외부/내부 스타일보다 우선합니다.


margin, padding, inset 축약형
        축약형의 방향 : 상 우 하 좌 (4)
        축약형의 방향 : 상 좌우 하 (3)
        축약형의 방향 : 상하 좌우 (2)


박스의 기본 성질

display:block
투명하다.
width: auto / height: auto
Y축으로 쌓여간다.
block 옆에 block이 오지 못하게 한다.


태그는 크게 inline 과 block 으로 나뉩니다.

 

inline 태그 (글자 그림 등 내용에 관여하는 태그)

<span></span>
<strong></strong>

<em></em>

<i></i>

<button></button>
<input />

나머지는 block 속성을 가집니다.


inline과 block의 차이
block 속성은 width height margin padding 값을 가집니다.

inline 속성은 좌우 margin padding 만을 가집니다. 상하 padding의 경우 background를 포함하여 padding이 적용된 것 처럼 보입니다.


attribute란 html 태그안에서 명시되는 속성들을 가리킵니다. ( class, id, href, src, etc. )
property란 CSS  스타일 적용을 위해 사용하는 속성들을 가리킵니다. ( width, display, position, etc. )


선택자 종류입니다.
 * 는 모든 선택자입니다. 
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
tag 선택자
      section li {
        color: #f00;
      }
      section li:nth-child(1) {
        color: #369;
      }

nth-child 는 자식의 순서를 기준으로 합니다.

ul 안에 li div 가 자식으로 존재한다면 div는 ul:nth-child(1)이 아니라 ul:nth-child(2) 입니다.

      section li:nth-child(1) {
        color: #369;
      }
      section div:nth-child(2) {
        color: #ff0;
      }

nth-of-type() 은 태그 타입별로 선택합니다.

section div:nth-of-type(2) {
        /* 태그 타입의 두번째를 기준으로 합니다. 2번째 div가 선택됩니다. */
        color: #0ff;
      }

class와 id모두에 적용될 때는 id가 우선됩니다.
      #color {
        color: #0f0;
      }
      .color {
        color: #359;
      }
~li 아래쪽의 형제 li 모두를 선택합니다.
      .color ~ li {
        color: rgb(255, 30, 240);
      }

+ li 인접형제 선택자 : 가장 인접한 아래의 형제를 하나 선택합니다.
      .color + li {
        color: chocolate;
      }
attr 선택자는 [ ] 안에 입력하며, attr로 선택할 수 있습니다.
      input[type="text"] {
        border: 1px solid #f00;
      }
      [class="color"] {
        background: #ff0;
      }
class&="class_name" * 표시는 "모든"을 의미합니다. col 이란 class를 가진 모든 attr을 선택합니다. 
      [class*="col"] {
        background: #ff0;
      }
, 를 이용할 때에는 주의해야 합니다. 아래의 경우

section 안의 ul, 그리고 모든 div 입니다.
section안의 ul과 section안의 div가 아닙니다,
      section ul,
      div {
        background: #ddd;
      }
section 안의 ul과 div 를 선택하는 올바른 형태는 아래와 같습니다. 착각하기 쉬우니 주의합니다.
      section ul,
      section div {
        background: #ddd;
      }

input 기본 테두리는 border / focus 상태에서 가장 밖에 나타나는 테두리는 outline 입니다.


다단메뉴를 만들기 전에 고정 메뉴를 구현해봅니다.

우선은 헤더의 로고, 메뉴 틀을 만듭니다.
      #header {
        line-height: 100px;
        background: #ddd;
      }
      #header .container {
        display: flex;
        width: 1200px;
        margin: 0 auto;
      }
logo와 메뉴 사이를 벌립니다.
      nav {
        margin: 0 0 0 auto;
      }
메뉴 사이의 간격을 벌립니다.
      nav > ul > li > a {
        display: block;
        padding: 0 40px;
      }
작은 메뉴의 위치를 absolute와 inset으로 조절합니다.
    nav > ul > li {
        position: relative;
      }
      nav > ul > li ul {
        /* top, right, bottom, left 대신에 inset: 0 0 0 0; 을 사용할 수 있습니다. */
        position: absolute;
        inset: 0 auto auto 0;
        background: #fff;
        z-index: 999;
        width: 100%;
      }
hover를 적용해봅니다. display: none;을 주어 고정되어 나타나던 메뉴창을 보이지 않게 합니다.
      nav > ul > li ul {
        position: absolute;
        inset: 90px auto auto 0;
        background: #fff;
        z-index: 999;
        display: none;
        width: 100%;
      }
hover가 될 경우 block을 주어 나타나도록 합니다.
      nav > ul > li:hover ul {
        display: block;
      }
가상요소 선택자로 메뉴의 윗부분을 뾰족하게 만들어 봅니다.
우선 박스를 만듭니다.
      nav > ul > li ul::before {
        content: "";
        position: absolute;
        inset: -10px auto auto 50%;
        transform: translateX(-50%) rotate(45deg);
        width: 20px;
        height: 20px;
        border: 1px solid #333;
        background: #fff;
      }
다음으로 박스를 가리기 위해 li에 position: relative; 와 background를 줍니다.
      nav > ul > li ul li {
        position: relative;
        background: #fff;
        border-bottom: 1px solid #ddd;
      }

동그랗게 만들어 주기도 합니다.
      nav > ul > li:nth-child(2) ul::before {
        content: "";
        position: absolute;
        inset: -10px auto auto 50%;
        transform: translateX(-50%) rotate(45deg);
        width: 20px;
        height: 20px;
        border: 3px solid #f00;
        border-radius: 50%;
        background: #fff;
        z-index: 999;
      }
하지만 가상요소선택자 ::before는 box-sizing: border-box; 가 적용되어 있지 않습니다.

별도로 속성을 줍니다.

        box-sizing: border-box;


아래에서 위로 나타나는 애니메이션을 적용해봅니다. 

display: none;과 같이 수치가 없는(중간 값이 없는) 경우에는 애니메이션이 적용되지 않습니다.
dispaly 속성을 없애고, inset으로 높이와 opacity로 보이지 않게 합니다.

      nav > ul > li ul {
        position: absolute;
        inset: 150px auto auto 50%;
        z-index: 999;
        width: 200px;
        transform: translateX(-50%);
        background: #fff;
        border: 4px solid #369;
        opacity: 0;
      }

opacitiy: 0; 의 경우에는 화면 상에 보이지만 않을 뿐 실제로는 위치하고 있기 때문에 메뉴가 있을 자리에 hover를 하면 메뉴가 나타나버립니다.
visibility로 아래에 위치해 있을 때 선택되지 않도록 합니다.
      nav > ul > li ul {

        ...
        +visibility: hidden;
      }
inset으로 높이를 조절하고 opacity로 다시 나타나게 합니다.  그리고 transition을 줍니다.
      nav > ul > li:hover ul {
        inset: 90px auto auto 50%;
        opacity: 1;
        visibility: visible;
        transition: 0.5s;
      }


이중 다단메뉴를 구현해봅니다.

 

우선 ul > li 로 header 라인의 메뉴버튼을 만듭니다. (ul > li)

그 안에 a로 menu01 버튼을 만든 뒤 같은 인덴트에 ul > li 로 sub menu01을 만듭니다. (ul > li ul > li)

마찬가지로 같은 인덴트에 ul > li > a 를 만들면 html구조는 완성됩니다. (ul > li ul > li ul > li)

css를 작업합니다. 위에서와 동일한 방법으로 sub 메뉴를 구현합니다.

      nav > ul > li {
        position: relative;
      }

      nav > ul > li > ul {
        position: absolute;
        inset: 100px auto auto 50%;
        width: 100%;
        transform: translateX(-50%);
        background: yellow;
        opacity: 0;
        transition: 0.2s;
        visibility: hidden;
      }

      nav > ul > li:hover ul {
        opacity: 1;
        visibility: visible;
      }

hover의 기준이 되어 줄 "sub menu" 01~05에 position: relative 속성을 적용합니다.

위의 ul>li 바로 아래의 ul>li 가 되어야 합니다. 헷갈리지 않도록 클래스를 주어도 됩니다.

      nav > ul > li > ul > li {
        position: relative;
      }

여기서 마지막 ul은 "sub sub menu01~05" 를 담고 있는 덩어리 입니다.
      nav > ul > li > ul > li ul {
        position: absolute;
        inset: 0 auto auto 100%;
        width: 100%;
        opacity: 0;
      }

a 에 배경을 주었습니다. a를 보이지 않도록 합니다.
      nav > ul > li > ul > li > ul > li > a {
        display: none;
      }

hover의 기준은 "sub menu" 01~05가 되어야 합니다. 두번째 ul의 li가 01~05입니다.
      nav > ul > li > ul > li:hover ul > li > a {
        display: block;
      }