ㆍProject Diary/HTML + CSS +JS (Haitai WepSite)
오늘은 반응형 네비게이션 메뉴를 만드는 프로젝트를 진행했다.
먼저 HTML로 기본 구조를 잡았다. 그런 다음 CSS로 스타일링을 해서 다양한 화면 크기에서도 잘 보이도록 했다. 마지막으로 JavaScript를 사용해 메뉴가 부드럽게 열리고 닫히도록 애니메이션 효과를 추가했다.
1. HTML 기본 구조 설정
헤더 섹션에 네비게이션 메뉴를 포함하는 구조다.
네비게이션 메뉴는 두 개의 뎁스로 구성된다: 뎁스1(depth1)과 뎁스2(depth2).
뎁스1은 네비게이션 메뉴의 최상위 항목으로 이 항목들은 화면에 항상 보이며, [제품소개],[달콤함 세상],[이벤트],[고객센터],[회사소개]가 이에 해당된다.
그리고 제품소개 메뉴를클릭하면 나오는 해태제과 캐릭터, 비스켓, 스낵 등이 뎁스2에 해당된다.
2. JavaScript로 동작 구현
2-1. 반응형 설정 함수 작성
화면 크기에 따라 PC와 모바일 버전을 구분하는 함수를 작성.
함수 정의 : 'getWindowWidth'
윈도우 너비를 확인하고, 너비에 따라 HTML 클래스와 스타일을 변경하는 getWindowWidth함수를 정의함
function getWindowWidth() {
// 현재 윈도우의 너비를 변수 'ww'에 저장
let ww = $(window).width();
if (ww > 1089) {
// PC 버전 설정
$("html").addClass("pc").removeClass("mobile"); // 'pc' 클래스를 추가하고 'mobile' 클래스를 제거
$("#header #nav").css({
display: "flex", // 네비게이션을 flexbox로 표시
width: "auto", // 너비를 자동으로 설정
});
$("#header .depth1 > li").removeClass("on").find(".depth2").hide(); // 모든 뎁스1 항목에서 'on' 클래스를 제거하고 뎁스2 메뉴를 숨김
if ($("#header #nav").parent().is(".cover")) {
$("#header #nav").unwrap(); // 만약 네비게이션의 부모 요소가 '.cover' 클래스가 있다면 해당 부모 요소를 제거
}
} else {
// 모바일 버전 설정
$("html").addClass("mobile").removeClass("pc"); // 'mobile' 클래스를 추가하고 'pc' 클래스를 제거
$("#header #nav").css({
display: "none", // 네비게이션을 숨김
width: "100%", // 너비를 100%로 설정
});
$("#header .menuopen").find("i").removeClass("fa-times").addClass("fa-bars"); // 햄버거 메뉴 아이콘을 'fa-bars' 클래스로 변경
$("#header #nav").removeClass("on"); // 네비게이션에서 'on' 클래스를 제거
$("nav .depth1 > li").removeClass("on"); // 모든 뎁스1 항목에서 'on' 클래스를 제거
}
}
함수 호출
페이지가 로드될 때 getWindowWidth 함수를 호출하여 초기 상태를 설정
getWindowWidth();
윈도우 리사이즈 이벤트 핸들러
윈도우가 리사이즈될 때마다 getWindowWidth 함수를 호출하여 상태를 업데이트
$(window).resize(function () {
getWindowWidth();
});
클릭 이벤트 핸들러 설정
네비게이션 메뉴의 토글 동작과 아이콘 변경을 관리
$("#header .menuopen").on("click", function () {
// 클릭된 요소(this)의 다음 요소를 슬라이드 토글 (보이기/숨기기)
$(this).next().stop().slideToggle(200);
// 클릭된 요소 안에 있는 <i> 요소가 'fa-bars' 클래스를 가지고 있는지 확인
if (!$(this).find("i").hasClass("fa-bars")) {
// 'fa-bars' 클래스가 없을 경우 (즉, 현재 'fa-times' 클래스일 경우)
// 모든 뎁스2 메뉴를 슬라이드 업 (숨기기)
$("#header #nav .depth2").slideUp();
// 모든 뎁스1 항목에서 'on' 클래스를 제거
$("#nav .depth1 > li").removeClass("on");
// 아이콘을 'fa-bars'로 변경하고 'fa-times' 클래스를 제거
$(this).find("i").addClass("fa-bars").removeClass("fa-times");
} else {
// 'fa-bars' 클래스가 있을 경우 (즉, 현재 'fa-bars' 클래스일 경우)
// 아이콘을 'fa-times'로 변경하고 'fa-bars' 클래스를 제거
$(this).find("i").addClass("fa-times").removeClass("fa-bars");
}
});
이렇게 동작을 주고나면
반응형 네비게시연 메뉴 완성!
2-2. 네비게이션 메뉴 동작 설정
뎁스크탑과 모바일 버전의 네비게이션 메뉴 동작 설정
// 뎁스1의 네비게이션 항목에 마우스를 올리거나 뗄 때 실행되는 이벤트
$("#nav .depth1 > li").on("mouseover mouseout", function () {
// HTML 태그에 'pc' 클래스가 있는 경우에만 동작
if ($("html").hasClass("pc")) {
// .subbg 요소를 슬라이드 토글 (열리거나 닫히는 애니메이션) 시킴
$(".subbg").stop().slideToggle(200);
// .subnavImg 요소를 슬라이드 토글 (열리거나 닫히는 애니메이션) 시킴
$(".subnavImg").stop().slideToggle(200);
// .depth2 요소를 슬라이드 토글 (열리거나 닫히는 애니메이션) 시킴
$(".depth2").stop().slideToggle(200);
}
});
// 뎁스2의 네비게이션 항목에 마우스를 올리거나 뗄 때 실행되는 이벤트
$("#nav .depth1 .depth2 > li").on("mouseover mouseout", function () {
// HTML 태그에 'pc' 클래스가 있는 경우에만 동작
if ($("html").hasClass("pc")) {
// 현재 항목의 부모 요소 (즉, .depth1 > li 요소)에 'on' 클래스를 토글
$(this).parent().parent().toggleClass("on");
// 현재 항목의 부모 요소의 형제 요소들에서 'on' 클래스를 제거
$(this).parent().parent().siblings().removeClass("on");
}
});
// 뎁스1의 네비게이션 항목을 클릭할 때 실행되는 이벤트
$("#nav .depth1 > li").on("click", function () {
// HTML 태그에 'mobile' 클래스가 있는 경우에만 동작
if ($("html").hasClass("mobile")) {
// 현재 클릭된 항목에 'on' 클래스를 토글
$(this).toggleClass("on");
// 클릭된 항목의 형제 요소들에서 'on' 클래스를 제거
$(this).siblings().removeClass("on");
}
});
// 뎁스2의 네비게이션 항목에 마우스를 올리거나 뗄 때 실행되는 이벤트
$("#nav .depth1 .depth2 > li").on("mouseover mouseout", function () {
// 현재 항목에 'on' 클래스를 토글
$(this).toggleClass("on");
// 현재 항목의 형제 요소들에서 'on' 클래스를 제거
$(this).siblings().removeClass("on");
});
데스크탑 모드:
- 뎁스1의 메뉴 항목에 마우스를 올리면 서브 메뉴 배경, 서브 메뉴 이미지, 뎁스2의 메뉴가 슬라이드 애니메이션과 함께 나타나거나 사라진다.
- 뎁스2의 메뉴 항목에 마우스를 올리면 해당 항목의 부모(.depth1 > li)에 on 클래스가 토글되고, 형제 항목의 on 클래스가 제거된다.
모바일 모드:
- 뎁스1의 메뉴 항목을 클릭하면 해당 항목에 on 클래스가 토글되고, 형제 항목의 on 클래스가 제거된다.
2-3. 하위 메뉴 이미지 토글 설정
하위 메뉴의 이미지 토글 기능을 설정
// 첫 번째 수준의 네비게이션 항목에 마우스를 올리거나 뗄 때 실행되는 이벤트
$("#nav .depth1 > li").hover(
function () {
// 마우스를 올린 항목의 인덱스를 가져옴
let index = $(this).index();
// 해당 인덱스에 맞는 클래스 (sn0, sn1, sn2 등)를 .subnavImg 요소에 추가
$(".subnavImg").addClass("sn" + index);
// 인덱스를 data 속성에 저장하여 나중에 사용할 수 있도록 함
$(this).data("hoveredIndex", index);
},
function () {
// 마우스를 뗀 항목의 인덱스를 data 속성에서 가져옴
let index = $(this).data("hoveredIndex");
// 해당 인덱스에 맞는 클래스 (sn0, sn1, sn2 등)를 .subnavImg 요소에서 제거
$(".subnavImg").removeClass("sn" + index);
}
);