오늘은 2차 메뉴의 일종인 드롭다운 메뉴를 만들어 보자. 이번에 만들 메뉴는 마우스를 통해 1차 메뉴를 가리키면 2차 메뉴가 내려오며 나타나는 일명 드롭다운 기능을 구현해 보자. 드롭다운 메뉴는 1차 메뉴보다 많은 수의 항목을 소화할 뿐 아니라, 포괄적인 개념의 메뉴 안에 세세한 개념을 담은 메뉴를 담음으로써 사용자가 원하는 항목을 찾아가는 것에 있어 도움을 줄 수 있다. 그뿐만 아니라 인터페이스를 체계적으로 관리하는 것과 동시에 시각적으로도 깔끔한 느낌을 줄 수 있다는 많은 장점을 갖고 있다. 이러한 메뉴를 position 속성을 이용하여 만들어 보자. 완성된 최종 코드는 포스팅의 마지막에 정리해 두겠다.
우선 완성된 이미지를 보자
가로로 길게 늘어진 하나의 메뉴 박스 안에 4개의 메뉴 항목이 담겨있고, 이 중 세 번째 메뉴에 마우스 포인터를 올려두게 되면 해당 메뉴 안에 들어있는 2차 메뉴가 내려오게 되는 모습을 볼 수 있다. 위와 같은 메뉴를 드롭다운 메뉴라고 한다.
기본 마크업부터 살펴보자
<header class="top-bar con-min-width">
<div class="con">
<nav class="top-bar__menu-box-1">
<ul>
<li>
<a href="#">menu1</a>
<ul>
<li><a href="#">text1</a></li>
<li><a href="#">text2</a></li>
<li><a href="#">text3</a></li>
<li><a href="#">text4</a></li>
</ul>
</li>
<li>
<a href="#">menu2</a>
<ul>
<li><a href="#">text1</a></li>
<li><a href="#">text2</a></li>
<li><a href="#">text3</a></li>
<li><a href="#">text4</a></li>
</ul>
</li>
<li>
<a href="#">menu3</a>
<ul>
<li><a href="#">text1</a></li>
<li><a href="#">text2</a></li>
<li><a href="#">text3</a></li>
<li><a href="#">text4</a></li>
</ul>
</li>
<li>
<a href="#">menu4</a>
<ul>
<li><a href="#">text1</a></li>
<li><a href="#">text2</a></li>
<li><a href="#">text3</a></li>
<li><a href="#">text4</a></li>
</ul>
</li>
</ul>
</nav>
</div>
</header>
위의 HTML 코드를 아무런 CSS 작업 없이 출력한다면 아래와 같은 모습을 보인다.
우리가 원하는 드롭다운 메뉴 바의 모습을 만들기 위해서는 우선 노멀라이즈 과정을 통해 태그의 기본 옵션 중 내가 원하지 않는 옵션들을 제거해 주어야 내가 원하는 형태로 만들어 나가기 수월해진다. 불필요한 요소들을 제거해 보자.
/* 노멀라이즈 시작 */
body, ul, li {
margin: 0;
padding: 0;
list-style: none; /* 해당 태그의 list-style을 none으로 하는 것으로 ●을 제거한다 */
}
a {
color: inherit; /* 부모 엘리먼트의 값을 물려받는다 */
text-decoration: none; /* 해당 태그의 text-decoration을 none으로 하는 것으로 밑줄을 제거한다 */
}
/* 노멀라이즈 끝 */
위의 노멀라이즈를 적용해 보자
위의 이미지를 본다면, 우리가 마크업 한 모든 메뉴의 항목들이 나와 있는 것을 볼 수 있다. 하지만 우리가 메뉴를 만들어 나가는 것에 있어서 1차 메뉴, 2차 메뉴 구분 없이 모든 메뉴가 계속해서 노출된다면 작업을 하기 어려움이 생길 수밖에 없을 것이다. 그러니 우선 2차 메뉴의 목록들을 보이지 않게 숨겨둔 뒤, 1차 메뉴부터 우리가 원하는 모습으로 만들어 준 다음 2차 메뉴를 소환하는 방식이 필요하다. 이러한 모습은 궁극적으로 우리가 만들고자 하는 드롭다운 메뉴의 작동 구성이기도 하다. 2차 메뉴를 숨기는 것은 2차 메뉴의 display 속성을 none 값으로 하는 것으로 해결할 수 있다.
/* 2차 이상의 메뉴만 none 값을 주기 */
.top-bar__menu-box-1 > ul ul {
display: none;
}
/* 보기 편하게 글씨 크기를 키운다 */
a {
font-size: 3rem;
}
위의 속성들을 적용해 보자
이제 메뉴 바를 만들 수 있는 모습이 되었다. 다음으로 메뉴들을 가운데로 가져오는 작업을 하는 것과 동시에 메뉴들을 가로로 나열해 보도록 하자. 이 과정은 이전 1차 메뉴를 만드는 포스팅에서 했던 것과 같이 con과 con-min-width 등의 속성을 만들어 처리할 것이다. 해당 과정이 궁금하다면 아래의 포스팅을 참고하여 추가로 학습하고 오길 바란다.
코드의 확장성을 위해 추가 학습하고 오는 것을 추천한다.
[HTML/CSS] 1차 메뉴 바 만들기 : 마우스를 인식해 보자
/* 가운데 정렬 */
.con {
margin-left: auto;
margin-right: auto;
}
/* 변수 생성 */
:root {
--site-width: 1200px;
}
/* 사이트 최소 너비 설정 */
.con-min-width {
min-width: var(--site-width);
}
/* 실질적으로 메뉴에 사용할 너비 설정 */
.top-bar > .con {
width: var(--site-width);
}
/* 실질적으로 메뉴에 사용할 너비 설정 */
.top-bar__menu-box-1 > ul > li {
display: inline-block;
}
/* 문자열 가운데 정렬 */
.top-bar__menu-box-1 {
text-align: center;
margin-top: 100px;
}
/* 모든 메뉴 박스의 배경을 검은색으로 하고 글자를 하얀색으로 꾸며보자 */
.top-bar__menu-box-1 ul {
background-color: black;
color: white;
}
위의 속성들을 적용해 보자
이제 어느 정도 틀이 잡혔으니 메뉴들의 크기를 조절해 보자. 이번 포스팅에서도 마우스 포인터가 메뉴를 인식하는 범위를 확장하기 위해 inline 값을 가진 <a> 태그를 block 값으로 만들어 줄 필요가 있다. 이후 padding 속성을 이용해 크기를 조절해 주도록 하자.
/* 모든 메뉴 크기 조절 */
.top-bar__menu-box-1 ul > li > a {
display: block;
font-size: 3rem;
padding: 10px 50px;
border: 10px solid red;
}
위의 속성들을 적용해 보자
위 사진에서 메뉴 간에 공백이 생기는 것을 볼 수 있다. 우선 이번 포스팅은 드롭다운 메뉴를 만드는 것을 목표로 진행하지만, 이러한 문제에 관해서는 지난 포스팅에서 다루었던 내용이니 이러한 현상이 생기는 이유나 해결 방법이 궁금하다면 아래의 포스팅을 살펴보는 것을 추천한다.
[HTML/CSS] 1차 메뉴 바 만들기 : inline-grid를 이용하자
이제는 여태까지 애써 외면해 두었던 2차 메뉴를 꺼내 볼 차례이다. 우리는 드롭다운 2차 메뉴의 활용을 position 속성을 이용해 구현해 보도록 하자. 그러기 위해서는 우선 hover 기능을 이용해 1차 메뉴에 적용을 시킬 필요가 있다. 위에서 2차 메뉴를 숨기기 위해 2차 메뉴에 none 값을 주었다면, 1차 메뉴가 마우스 포인터를 인식하면 2차 메뉴에 block의 값을 주는 것으로 등장시킬 수 있다. 일단 한번 실행해 보자.
/* 모든 메뉴를 마우스 인식 시 배경색을 변경 */
.top-bar__menu-box-1 ul > li:hover > a {
background-color: #555;
}
/* 2차 메뉴가 보이도록 만들어 보자 */
.top-bar__menu-box-1 > ul > li:hover > ul {
display: block;
}
위의 속성들을 적용해 보자
누가 말해주지 않아도 무언가 잘못되었다는 것을 알 수 있다. 위와 같은 문제는 왜 발생하는 걸까? 정답은 말 그대로 2차 메뉴가 등장했기 때문이다. 우리가 2차 메뉴에 block의 값을 주면서 메뉴 박스에 영향을 미치게 되는 것이다. 그러면 다른 값을 주면 되는 건가? 사실 inline을 주던 inline-block을 주던 메뉴 박스 안에 존재하는 이상 영향을 줄 수밖에 없다. 그렇기에 우리는 2차 메뉴를 메뉴 박스에 가두어 두는 것이 아니라 독립적으로 존재하 만들어 주면 된다.
이것을 가능하게 만들어 주는 것이 position 속성의 absolute이다. absolute position은 부모의 속박에서 벗어나 화면상에 어디든지 원하는 위치에 위치시킬 수 있고, 물론 이때 다른 요소에 영향을 미치지도 않는다. 단, 상위 엘리먼트 중에 position 속성이 relative인 엘리먼트가 존재한다면, 해당 엘리먼트의 내부 영역에서만 자유롭게 존재할 수 있다. 우리는 이 점을 이용하여 1차 메뉴에 relative를 주고, 2차 메뉴에 absolute를 주는 것이다. 이후 2차 메뉴의 위치를 1차 메뉴의 아래쪽에 위치시키면 우리가 원하는 드롭다운 메뉴를 만들 수 있게 된다.
/* 1차 메뉴를 제한 구역으로 설정 */
.top-bar__menu-box-1 > ul > li {
position: relative;
}
/* 2차 메뉴에 absolute 값을 주기 */
.top-bar__menu-box-1 > ul > li > ul {
position: absolute;
top: 100%; /* 2차 메뉴를 1차 메뉴의 아래에 위치시킨다 */
left: 0; /* 2차 메뉴를 1차 메뉴의 왼쪽 벽에 붙인다 */
width: 100%; /* 부모의 너비를 그대로 받아온다 */
}
위의 속성들을 적용해 보자
top 속성은 우리가 주는 값만큼 위쪽에 공간을 만들게 되는데, 이런 공간을 부모 엘리먼트의 높이 100%를 주는 것으로 부모 엘리먼트 바로 아래 위치시킬 수 있게 된다. 이제 우리가 원하던 드롭다운 메뉴가 완성되었다. 추가로 외적인 요소를 조금만 다듬어 준다면 보다 보기 좋은 메뉴를 만들 수 있을 것 같으니 한 번 해보도록 하자.
@import url('https://fonts.googleapis.com/css2?family=Ubuntu&display=swap');
html {
font-family: 'Ubuntu', sans-serif;
}
body {
background-color: #bababa;
}
/* 메뉴 박스의 모서리를 둥글게 해주자 */
.top-bar__menu-box-1 > ul {
border-radius: 20px;
}
위의 속성들을 적용해 보자
쨔쟌-! 드디어 우리가 원하는 드롭다운 기능을 갖춘 메뉴 바를 만들어 보았다. 드롭다운으로서 가져야 할 것들은 충분히 잘 갖추었고, 이를 잘 활용하기만 한다면 3차 드롭다운 메뉴도 어렵지 않게 만들 수 있다. 물론 완벽하다고는 할 수 없지만, 이를 보완해 나가는 것은 inline-grid 포스팅 참고해 해결할 수 있으니 직접 참고하여 해결해 보는 것도 좋은 방법이다. 다음 시간에는 사이드바 메뉴에 대하여 포스팅하는 시간을 가져보도록 하자.
[HTML/CSS] 사이드바 메뉴 만들기 : 나타나는 2차 메뉴 만들기 feat. transform: translate
위 단계들의 종합 CSS 코드를 남기며 이번 포스팅을 마친다.
/* 폰트 시작 */
@import url('https://fonts.googleapis.com/css2?family=Ubuntu&display=swap');
html {
font-family: 'Ubuntu', sans-serif;
}
/* 폰트 끝 */
/* 노멀라이즈 시작 */
body, ul, li {
margin: 0;
padding: 0;
list-style: none; /* 해당 태그의 list-style을 none으로 하는 것으로 ●을 제거한다 */
}
body {
background-color: #bababa;
}
a {
color: inherit; /* 부모 엘리먼트의 값을 물려받는다 */
text-decoration: none; /* 해당 태그의 text-decoration을 none으로 하는 것으로 밑줄을 제거한다 */
}
/* 노멀라이즈 끝 */
/* 라이브러리 시작 */
.con {
margin-left: auto;
margin-right: auto;
}
/* 라이브러리 끝 */
/* 커스텀 시작 */
:root {
--site-width: 1200px;
}
.con-min-width {
min-width: var(--site-width);
}
.top-bar > .con {
width: var(--site-width);
}
/* 드롭다운 메뉴 시작 */
.top-bar__menu-box-1 > ul ul {
display: none;
}
.top-bar__menu-box-1 > ul > li {
display: inline-block;
}
.top-bar__menu-box-1 {
text-align: center;
margin-top: 100px;
}
.top-bar__menu-box-1 ul {
background-color: black;
color: white;
}
.top-bar__menu-box-1 ul > li > a {
display: block;
font-size: 3rem;
padding: 10px 50px;
}
.top-bar__menu-box-1 ul > li:hover > a {
background-color: #555;
}
.top-bar__menu-box-1 > ul > li {
position: relative;
}
.top-bar__menu-box-1 > ul > li > ul {
position: absolute;
top: 100%;
left: 0;
width: 100%;
}
.top-bar__menu-box-1 > ul > li:hover > ul {
display: block;
}
.top-bar__menu-box-1 > ul {
border-radius: 20px;
}
/* 드롭다운 메뉴 끝 */
/* 커스텀 끝 */
'웹 프로그래밍 > 프론트엔드' 카테고리의 다른 글
[HTML/CSS] Position (absolute와 relative) & z-index를 활용해 보자 (0) | 2023.05.19 |
---|---|
[HTML/CSS] transform-origin & rotate를 사용하자 : 변신하는 아이콘 만들기 feat. position (0) | 2023.05.18 |
[HTML/CSS] 사이드바 메뉴 만들기 : 나타나는 2차 메뉴 만들기 feat. transform: translate (0) | 2023.05.16 |
[HTML/CSS] 1차 메뉴 바 만들기 : inline-grid를 이용하자 (0) | 2023.05.14 |
[HTML/CSS] 1차 메뉴 바 만들기 : 마우스를 인식해 보자 (0) | 2023.05.13 |
댓글