안녕하세요! 웹스토리보이입니다 😊
좋습니다! 이제 메뉴 유형 중 마지막 단계인 배경이 들어가는 M-6 유형까지 오셨네요
기존의 원리를 잘 이해하셨다면, 이 유형도 수월하게 따라가실 수 있을 거예요. 배경이 전체적으로 펼쳐지는 구조만 다를 뿐, 스크립트와 선택자 활용 방식은 유사하니 자신감을 갖고 시작해봅시다. 😊
이 유형은 배경이 슬라이드와 함께 자연스럽게 보여지게 처리하는 게 핵심이에요. 먼저 CSS로 .nav-bg처럼 배경 요소를 준비하고, 마우스 오버 시 해당 배경이 슬라이드처럼 펼쳐지는 효과를 자바스크립트나 제이쿼리로 구현하는 방식입니다. 준비되셨나요? 이제 마지막 단계도 함께 완성해봐요!! 렛츠 기릿! 💪😇
이번에는 D-1 유형 레이아웃에 메뉴 유형을 작업을 해보겠습니다. 기본적인 코드는 그대로 복사하셔서 사용하셔도 됩니다.
1<body>
2 <div id="wrap">
3 <aside id="aside">
4 <h1></h1>
5 <nav></nav>
6 </aside>
7 <!-- //aside -->
8
9 <main id="main">
10 <article id="slider"></article>
11 <article id="link"></article>
12 <section id="contents">
13 <div class="content1"></div>
14 <div class="content2"></div>
15 </section>
16 </main>
17 <!-- //main -->
18
19 <footer id="footer">
20 <div class="footer1"></div>
21 <div class="footer2">
22 <div class="footer2-1"></div>
23 <div class="footer2-2"></div>
24 </div>
25 <div class="footer3"></div>
26 </footer>
27 <!-- //footer -->
28 </div>
29 <!-- //wrap -->
30</body>
1* {
2 margin: 0;
3 padding: 0;
4}
5li {
6 list-style: none;
7}
8a {
9 text-decoration: none;
10 color: #000;
11}
12#wrap {
13 width: 100%;
14 display: flex;
15 flex-wrap: wrap;
16}
17#aside {
18 width: 200px;
19}
20#aside h1 {
21 width: 100%;
22 height: 100px;
23 background-color: #efefef;
24}
25#aside nav {
26 width: 100%;
27 height: 700px;
28 background-color: #e3e3e3;
29}
30#main {
31 width: calc(100% - 200px);
32}
33#slider {
34 width: 100%;
35 height: 400px;
36 background-color: #d9d9d9;
37}
38#link {
39 width: 100%;
40 height: 150px;
41 background-color: #d1d1d1;
42}
43#contents {
44 width: 100%;
45 display: flex;
46}
47#contents .content1 {
48 width: 50%;
49 height: 250px;
50 background-color: #c7c7c7;
51}
52#contents .content2 {
53 width: 50%;
54 height: 250px;
55 background-color: #bcbcbc;
56}
57#footer {
58 width: 100%;
59 display: flex;
60}
61#footer .footer1 {
62 width: 20%;
63 height: 120px;
64 background-color: #b1b1b1;
65}
66#footer .footer2 {
67 width: 60%;
68}
69#footer .footer2 .footer2-1 {
70 width: 100%;
71 height: 60px;
72 background-color: #a3a3a3;
73}
74#footer .footer2 .footer2-2 {
75 width: 100%;
76 height: 60px;
77 background-color: #9d9d9d;
78}
79#footer .footer3 {
80 width: 20%;
81 height: 120px;
82 background-color: #929292;
83}
메뉴 코드를 추가하고 CSS를 설정하겠습니다. 전체 배경이 오른쪽에 나오기 때문에 main 요소에 가상요소를 작업해야 합니다. 만약 사이드 영역에 가상요소를 잡으면 전체 영역을 잡을 수 없기 때문에 상관이 없는 메인 영역에 가상요소를 작업해야 합니다. 해당 메뉴의 서브 메뉴들은 position: absolute를 이용하여 각각 위치값을 설정해야 합니다. 구조상 이게 제일 편한 방법일 것 같습니다. 혹시 더 좋은 의견이 있으면 댓글 부탁드립니다. 어째든 배경이 될 수 있는 요소는 메인 영역에 설정하고, 서브메뉴는 절대 위치를 통해 위치를 억지로 잡아줬습니다.
1<nav class="nav">
2 <ul>
3 <li>
4 <a href="#">메뉴1</a>
5 <ul class="submenu">
6 <li><a href="#">서브메뉴1-1</a></li>
7 <li><a href="#">서브메뉴1-2</a></li>
8 <li><a href="#">서브메뉴1-3</a></li>
9 <li><a href="#">서브메뉴1-4</a></li>
10 </ul>
11 </li>
12 <li>
13 <a href="#">메뉴2</a>
14 <ul class="submenu">
15 <li><a href="#">서브메뉴2-1</a></li>
16 <li><a href="#">서브메뉴2-2</a></li>
17 <li><a href="#">서브메뉴2-3</a></li>
18 </ul>
19 </li>
20 <li>
21 <a href="#">메뉴3</a>
22 <ul class="submenu">
23 <li><a href="#">서브메뉴3-1</a></li>
24 <li><a href="#">서브메뉴3-2</a></li>
25 </ul>
26 </li>
27 <li>
28 <a href="#">메뉴4</a>
29 <ul class="submenu">
30 <li><a href="#">서브메뉴4-1</a></li>
31 <li><a href="#">서브메뉴4-2</a></li>
32 <li><a href="#">서브메뉴4-3</a></li>
33 </ul>
34 </li>
35 <li>
36 <a href="#">메뉴5</a>
37 <ul class="submenu">
38 <li><a href="#">서브메뉴5-1</a></li>
39 </ul>
40 </li>
41 </ul>
42</nav>
::after 가상 요소 속성을 이용해서 전체 영역을 설정했습니다. 위치는 position: absolute를 이용해서 잡아주고, 기준점이 되는 메인 영역에 position: relative를 설정했습니다. 나중에 스크립트로 클래스 on이 붙으면 width: 100%;가 설정되어 있기 때문에 배경이 활성화 될 것입니다. 서브 메뉴들의 위치는 nth-child()를 이용하면, 자식들을 선택적으로 선택할 수 있습니다.
1/* nav */
2.nav {
3 position: relative;
4 z-index: 1000;
5}
6.nav > ul > li {
7 position: relative;
8}
9.nav > ul > li > a {
10 padding: 10px;
11 display: block;
12 text-align: center;
13 background-color: #ccc;
14}
15.nav > ul > li > a:hover {
16 background-color: #aeaeae;
17}
18.nav > ul > li > ul {
19 position: absolute;
20 right: -500px;
21 top: 0;
22 width: 500px;
23 display: none;
24}
25.nav > ul > li > ul > li {
26 display: inline;
27}
28.nav > ul > li > ul > li > a {
29 padding: 10px;
30 display: inline-block;
31 width: 100px;
32}
33.nav > ul > li > ul > li > a:hover {
34 background-color: #a2a2a2;
35}
36#main {
37 position: relative;
38}
39#main::after {
40 content: '';
41 width: 0%;
42 height: 193px;
43 background-color: #b0b0b0;
44 position: absolute;
45 left: 0;
46 top: 100px;
47 z-index: 1;
48 transition: all 300ms;
49}
50#main.on::after {
51 width: 100%;
52}
jQuery 라이브러리를 먼저 연동하고, 그 다음 $() 문법 안에 function()을 넣어 제이쿼리의 시작을 선언해줍니다. 이건 마치 "문서가 모두 로드되면 이 코드를 실행해줘!"라는 의미라고 생각하시면 됩니다.
그 안에서 우리가 원하는 두 가지 동작을 구현할 건데요. 첫 번째는 서브메뉴가 천천히 나타나는 효과입니다. 이전 메뉴 유형에서는 .slideDown()을 사용해서 위에서 아래로 펼쳐지는 듯한 애니메이션을 구현했다면, 이번에는 .fadeIn()을 사용해 부드럽게 서서히 나타나는 느낌을 줍니다. 두 번째는 메인 영역의 배경이 같이 펼쳐지는 효과입니다. 이건 CSS에서 ::after 가상 요소로 배경을 만들어 놓고, 자바스크립트에서는 #main에 .on 클래스를 붙였다 떼면서 배경의 가로 너비가 0 → 100%로 확장되도록 처리하는 구조입니다.
이때, jQuery에서 애니메이션이 겹치거나 밀리지 않도록 하기 위해 .stop() 메서드를 반드시 함께 써줘야 합니다. 그래야 마우스를 빠르게 움직였을 때 애니메이션이 꼬이지 않죠. 그리고 클래스를 추가하거나 제거하는 부분은 .addClass()와 .removeClass()를 사용하면 됩니다. 아주 직관적인 메서드들이죠. 말 그대로 "클래스를 추가하거나, 없애주기만 하면 되는" 방식입니다.
1<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
2<script>
3 $(function(){
4 $(".nav > ul > li").mouseover(function(){
5 $(".nav > ul > li > ul").stop().fadeIn();
6 $("#main").addClass("on");
7 });
8 $(".nav > ul > li").mouseout(function(){
9 $(".nav > ul > li > ul").stop().fadeOut();
10 $("#main").removeClass("on");
11 });
12 });
13</script>
자바스크립트로도 메뉴 동작을 충분히 구현할 수 있습니다. 기본적인 원리는 제이쿼리와 같고, 다만 메서드 이름과 문법이 조금 더 직관적이고 세부 설정이 필요하다는 점만 다릅니다. 이번 유형에서는 서브 메뉴가 천천히 펼쳐지는 애니메이션 대신, 단순히 보이고 안 보이는 상태만 전환하면 되기 때문에 style.display 속성을 사용했습니다. 즉, 마우스를 올리면 display: "block"으로 보여주고, 마우스를 떼면 display: "none"으로 숨겨주는 방식이죠.
그리고 두 번째로 중요한 점은 배경을 제어하는 방법입니다. 우리는 CSS에서 #main::after 가상 요소를 활용해서 배경을 만들었고, 그 배경의 활성화 여부는 클래스 .on이 붙었는지 아닌지로 판단하도록 했습니다. 그래서 자바스크립트에서는 마우스를 올렸을 때 main 요소에 classList.add("on")을 적용하고, 마우스를 떼면 classList.remove("on")을 적용하는 구조입니다.
여기서 핵심은, 스크립트는 단순히 클래스만 토글할 뿐이고, 실제 애니메이션은 CSS의 transition 속성이 처리해준다는 점이에요. 즉, 역할을 분리해서 스크립트는 상태만 제어, 스타일은 표현만 담당하게 만든 것이죠.
1window.onload = function(){
2 let navList = document.querySelector(".nav > ul");
3
4 navList.addEventListener("mouseover", function(){
5 navList.querySelectorAll(".submenu").forEach(sub => {
6 sub.style.display = "block";
7 });
8 document.getElementById("main").classList.add("on");
9 });
10 navList.addEventListener("mouseout", function(){
11 navList.querySelectorAll(".submenu").forEach(sub => {
12 sub.style.display = "none";
13 });
14 document.getElementById("main").classList.remove("on");
15 });
16}
마지막 메뉴 유형까지 정말 잘 따라오셨습니다! 이번 유형은 단순히 서브메뉴를 보여주는 것을 넘어, 전체 배경이 함께 펼쳐지는 효과를 연출하는 방법을 배웠어요. 이처럼 디자인 요소가 더해질수록 CSS와 자바스크립트가 협력하는 구조를 이해하는 것이 매우 중요합니다.
특히 이번 시간에는 가상 요소를 활용한 배경 제어, 클래스를 통한 트리거 방식, 그리고 자바스크립트와 제이쿼리 각각의 접근 방식을 비교하면서, 어떤 상황에서 어떤 도구를 활용할 수 있을지 감을 잡으셨을 거예요. 지금은 따라만 하고 있어도 괜찮습니다. 반복하다 보면 자연스럽게 이해가 되고, 어느 순간엔 직접 구조를 설계하고 구현할 수 있게 될 거예요. "왜 이렇게 짰는지"를 이해하려는 태도만 있어도 이미 절반은 성공한 셈입니다. 이제 메뉴 유형은 마무리되었지만, 여러분의 UI 구현 여정은 이제 시작입니다. 다음 시간엔 또 다른 실무 스타일의 인터페이스를 함께 구현해보면서, 실력을 하나 더 끌어올려보겠습니다.
포기하지 마시고, 하나씩 차근차근. 웹스토리보이는 언제나 여러분의 성장을 응원합니다! 😊💪