[HTML/CSS] 멀티 메뉴 구현

happyyeom·2024년 11월 1일


이렇게 3차 메뉴까지 만드는 법을 알아보자.

step 1

기본적인 마크업과 틀은 이렇다.
html

  • ul > li > a는 규칙이라고 알아두면 좋다.
  • ul은 ul을 자식으로 둘 수 없다.
  • a는 대부분의 경우 오직 텍스트만 가질 수 있다.
  • li는 li를 자식으로 둘 수 없다.
  • ul의 자식은 무조건 li이어야 한다.
  • li는 그 어떤 것도 자식으로 가질 수 있다.
    nav > ul > li > a + ul > li > a + ul > li > a ... 이런 형식이다.
<nav class="menu-box">
  <ul>
    <li>
      <a href="#">1차 메뉴 아이템 1</a>
      <ul>
        <li>
          <a href="#">2차 메뉴 아이템 1</a>
          <ul>
            <li><a href="#">3차 메뉴 아이템 1</a></li>
            <li><a href="#">3차 메뉴 아이템 2</a></li>
            <li><a href="#">3차 메뉴 아이템 3</a></li>
          </ul>
        </li>
        <li>
          <a href="#">2차 메뉴 아이템 2</a>
          <ul>
            <li><a href="#">3차 메뉴 아이템 1</a></li>
            <li><a href="#">3차 메뉴 아이템 2</a></li>
            <li><a href="#">3차 메뉴 아이템 3</a></li>
          </ul>
        </li>
        <li>
          <a href="#">2차 메뉴 아이템 3</a>
          <ul>
            <li><a href="#">3차 메뉴 아이템 1</a></li>
            <li><a href="#">3차 메뉴 아이템 2</a></li>
            <li><a href="#">3차 메뉴 아이템 3</a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li>
      <a href="#">1차 메뉴 아이템 2</a>
      <ul>
        <li>
          <a href="#">2차 메뉴 아이템 1</a>
          <ul>
            <li><a href="#">3차 메뉴 아이템 1</a></li>
            <li><a href="#">3차 메뉴 아이템 2</a></li>
            <li><a href="#">3차 메뉴 아이템 3</a></li>
          </ul>
        </li>
        <li>
          <a href="#">2차 메뉴 아이템 2</a>
          <ul>
            <li><a href="#">3차 메뉴 아이템 1</a></li>
            <li><a href="#">3차 메뉴 아이템 2</a></li>
            <li><a href="#">3차 메뉴 아이템 3</a></li>
          </ul>
        </li>
        <li>
          <a href="#">2차 메뉴 아이템 3</a>
          <ul>
            <li><a href="#">3차 메뉴 아이템 1</a></li>
            <li><a href="#">3차 메뉴 아이템 2</a></li>
            <li><a href="#">3차 메뉴 아이템 3</a></li>
          </ul>
        </li>
      </ul>
    </li>
    <li>
      <a href="#">1차 메뉴 아이템 3</a>
      <ul>
        <li>
          <a href="#">2차 메뉴 아이템 1</a>
          <ul>
            <li><a href="#">3차 메뉴 아이템 1</a></li>
            <li><a href="#">3차 메뉴 아이템 2</a></li>
            <li><a href="#">3차 메뉴 아이템 3</a></li>
          </ul>
        </li>
        <li>
          <a href="#">2차 메뉴 아이템 2</a>
          <ul>
            <li><a href="#">3차 메뉴 아이템 1</a></li>
            <li><a href="#">3차 메뉴 아이템 2</a></li>
            <li><a href="#">3차 메뉴 아이템 3</a></li>
          </ul>
        </li>
        <li>
          <a href="#">2차 메뉴 아이템 3</a>
          <ul>
            <li><a href="#">3차 메뉴 아이템 1</a></li>
            <li><a href="#">3차 메뉴 아이템 2</a></li>
            <li><a href="#">3차 메뉴 아이템 3</a></li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</nav>

css

/*노말라이즈*/
a{
  color:inherit;
  text-decoration:none;
}

.menu-box > ul ul{
  display:none;
}
/*
1차 메뉴 아이템들을 제외한 2차,3차 아이템들은 보이지 않아야 하므로 
.menu-box(nav태그)의 자식 ul태그(1차 메뉴 아이템들)의 후손 ul태그(2차,3차 메뉴 아이템들)
의 display속성을 none으로 만들어 보이지 않게 만든다.
*/

.menu-box li:hover > ul{
  display:block;
}
/*
큰 틀의 구조가 ul > li > ul > li ...이므로 n차 메뉴 뭉텅이(ul태그)는 그 부모인 li태그(n-1차 메뉴의 아이템들)
을 hover해야 나온다. 따라서 .menu-box의 후손인 li태그를 hover했을 때,
자식인 ul태그의 display속성을 block으로 만든다.
(1차 메뉴는 애초에 display속성이 block이고 부모인 li태그가 없기 때문에 이 속성에 해당되지 않는다.)
*/

step 2

1차 메뉴까지의 css작업을 완료해보자.
css

/*노말라이즈*/
a{
  color:inherit;
  text-decoration:none;
}

ul,li,body{
  list-style:none;
  padding:0;
  margin:0;
}

.menu-box > ul ul{
  display:none;
}
/*
1차 메뉴 아이템들을 제외한 2차,3차 아이템들은 보이지 않아야 하므로 
.menu-box(nav태그)의 자식 ul태그(1차 메뉴 아이템들)의 후손 ul태그(2차,3차 메뉴 아이템들)
의 display속성을 none으로 만들어 보이지 않게 만든다.
*/

.menu-box li:hover > ul{
  display:block;
}
/*
큰 틀의 구조가 ul > li > ul > li ...이므로 n차 메뉴 뭉텅이(ul태그)는 그 부모인 li태그(n-1차 메뉴의 아이템들)
을 hover해야 나온다. 따라서 .menu-box의 후손인 li태그를 hover했을 때, 
자식인 ul태그의 display속성을 block으로 만든다.
(1차 메뉴는 애초에 display속성이 block이고 부모인 li태그가 없기 때문에 이 속성에 해당되지 않는다.)
*/
.menu-box{
  text-align:center;
  font-weight:bold;
}
/*메뉴를 가운데로 정렬*/

.menu-box > ul{
  display:inline-block;
  /*display속성을 inline-block으로 만들어 text-align을 적용시킬 수 있게 만든다.*/
  background-color:rgba(0,0,0,0.4);
  padding:0 5px;
  /*양 옆 여백 부여*/
  border-radius:5px;
  /*모서리 부분 둥글게*/
}


.menu-box > ul > li{
  display:inline-block;
  /*inline-block으로 만들어 한 줄에 정렬시킨다.*/
}

.menu-box > ul > li > a{
  display:inline-block;
  padding:10px;
  /*inline-block으로 만들어 padding값이 적용되도록 만든다.
  (- a태그는 inline이어서 padding, width등의 값이 잘 적용되지 않는다.)*/
}

.menu-box > ul > li:hover > a{
  /*li박스가 호버되면 a태그에게 적용*/
  color:white;
  background-color:black;
}

step 3

2차 메뉴까지 css작업을 해보자.
css

/*노말라이즈*/
a{
  color:inherit;
  text-decoration:none;
}

ul,li,body{
  list-style:none;
  padding:0;
  margin:0;
}

.menu-box > ul ul{
  display:none;
}
/*
1차 메뉴 아이템들을 제외한 2차,3차 아이템들은 보이지 않아야 하므로 
.menu-box(nav태그)의 자식 ul태그(1차 메뉴 아이템들)의 후손 ul태그(2차,3차 메뉴 아이템들)
의 display속성을 none으로 만들어 보이지 않게 만든다.
*/

.menu-box li:hover > ul{
  display:block;
}
/*
큰 틀의 구조가 ul > li > ul > li ...이므로 n차 메뉴 뭉텅이(ul태그)는 그 부모인 li태그(n-1차 메뉴의 아이템들)
을 hover해야 나온다. 따라서 .menu-box의 후손인 li태그를 hover했을 때,
자식인 ul태그의 display속성을 block으로 만든다.
(1차 메뉴는 애초에 display속성이 block이고 부모인 li태그가 없기 때문에 이 속성에 해당되지 않는다.)
*/
.menu-box{
  text-align:center;
  font-weight:bold;
}
/*메뉴를 가운데로 정렬*/

.menu-box > ul{
  display:inline-block;
  /*display속성을 inline-block으로 만들어 text-align을 적용시킬 수 있게 만든다.*/
  padding:0 5px;
  /*양 옆 여백 부여*/
  border-radius:5px;
  /*모서리 부분 둥글게*/
}


.menu-box > ul > li{
  display:inline-block;
  /*inline-block으로 만들어 한 줄에 정렬시킨다.*/
}

/* 수정 전 선택자
.menu-box > ul > li > a
*/
.menu-box a{
  /*2차 3차 메뉴에도 적용될 수 있도록 후손 선택자로 변경*/
  display:inline-block;
  padding:10px;
  /*inline-block으로 만들어 padding값이 적용되도록 만든다.
  (- a태그는 inline이어서 padding, width등의 값이 잘 적용되지 않는다.)*/
}

/* 수정 전 선택자
.menu-box > ul > li:hover > a
  li박스가 호버되면 a태그에게 적용
*/
.menu-box li:hover > a{
  /*2차 3차 메뉴에도 적용될 수 있도록 후손 선택자로 변경*/
  color:white;
  background-color:black;
}

.menu-box ul{
  /* .menu-box의 후손인 모든 ul들에게 */
  background-color:rgba(0,0,0,0.4);
}

.menu-box > ul ul{
  /* 1차 메뉴를 제외한 2,3...차 메뉴들에게*/
  position:absolute;
}

.menu-box li{
  position:relative;
  /*기본 구조가 ul > li > ul > li > ...이기 때문에
  ul을 position:absolute로 만들고 그 부모인 li를 relative로 만들어
  기준으로 위치 조정을 할 수 있게 만든다.*/
}

step 4

이제 3차메뉴의 위치를 조정해주어야 한다. 이때 1차 메뉴 아이템3의 3차메뉴아이템들은 2차메뉴의 왼쪽에 나오게 해야 한다.
css

/*노말라이즈*/
a{
  color:inherit;
  text-decoration:none;
}

ul,li,body{
  list-style:none;
  padding:0;
  margin:0;
}

.menu-box > ul ul{
  display:none;
}
/*
1차 메뉴 아이템들을 제외한 2차,3차 아이템들은 보이지 않아야 하므로 
.menu-box(nav태그)의 자식 ul태그(1차 메뉴 아이템들)의 후손 ul태그(2차,3차 메뉴 아이템들)
의 display속성을 none으로 만들어 보이지 않게 만든다.
*/

.menu-box li:hover > ul{
  display:block;
}
/*
큰 틀의 구조가 ul > li > ul > li ...이므로 n차 메뉴 뭉텅이(ul태그)는 그 부모인 li태그(n-1차 메뉴의 아이템들)
을 hover해야 나온다. 따라서 .menu-box의 후손인 li태그를 hover했을 때, 
자식인 ul태그의 display속성을 block으로 만든다.
(1차 메뉴는 애초에 display속성이 block이고 부모인 li태그가 없기 때문에 이 속성에 해당되지 않는다.)
*/
.menu-box{
  text-align:center;
  font-weight:bold;
}
/*메뉴를 가운데로 정렬*/

.menu-box > ul{
  display:inline-block;
  /*display속성을 inline-block으로 만들어 text-align을 적용시킬 수 있게 만든다.*/
  padding:0 5px;
  /*양 옆 여백 부여*/
  border-radius:5px;
  /*모서리 부분 둥글게*/
}


.menu-box > ul > li{
  display:inline-block;
  /*inline-block으로 만들어 한 줄에 정렬시킨다.*/
}

/* 수정 전 선택자
.menu-box > ul > li > a
*/
.menu-box a{
  /*2차 3차 메뉴에도 적용될 수 있도록 후손 선택자로 변경*/
  display:inline-block;
  padding:10px;
  /*inline-block으로 만들어 padding값이 적용되도록 만든다.
  (- a태그는 inline이어서 padding, width등의 값이 잘 적용되지 않는다.)*/
}

/* 수정 전 선택자
.menu-box > ul > li:hover > a
  li박스가 호버되면 a태그에게 적용
*/
.menu-box li:hover > a{
  /*2차 3차 메뉴에도 적용될 수 있도록 후손 선택자로 변경*/
  color:white;
  background-color:black;
}

.menu-box ul{
  /* .menu-box의 후손인 모든 ul들에게 */
  background-color:rgba(0,0,0,0.4);
}

.menu-box > ul ul{
  /* 1차 메뉴를 제외한 2,3...차 메뉴들에게*/
  position:absolute;
}

.menu-box li{
  position:relative;
  /*기본 구조가 ul > li > ul > li > ...이기 때문에
  ul을 position:absolute로 만들고 그 부모인 li를 relative로 만들어
  기준으로 위치 조정을 할 수 있게 만든다.*/
}

.menu-box ul ul ul{
  top:0;
  /*위치를 position이 relative인 부모 기준으로 위 공백을 없앤다.*/
  left:100%;
  /*위치를 position이 relative인 부모 기준으로 왼쪽에 부모너비의 100%만큼 띄운다.
  (오른쪽에서 나타나게 한다.)*/
  white-space:nowrap;
  /*기본적으로 줄바꿈이 된 상태임으로 줄바꿈을 금지시킨다.*/
}

.menu-box > ul > li:last-child ul ul{
  /*1차 메뉴 아이템들 중 마지막 자식(1차 메뉴 아이템 3)의 자식의 3차 메뉴들*/
  left:-100%;
  /*위치를 position이 relative인 부모 기준으로 왼쪽에 부모너비의 100%만큼 띄운다.
  (왼쪽에서 나타나게 한다.)*/
}

.menu-box ul ul ul{
  white-space:nowrap;
  /*기본적으로 줄바꿈이 된 상태임으로 줄바꿈을 금지시킨다.*/
}

white-space:nowrap;을 하기 전에는 a태그나 li태그에 정해지 너비가 없기 때문에 줄 바꿈을 해서 나타난다. 그래서 줄바꿈을 금지시키는 것이다.

profile
🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳🌳

0개의 댓글