코딩
화면 너비에 따라 변하고 클릭 시 열리고 닫히는 메뉴 만들기
KUROMI98
2025. 7. 26. 13:19
html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<title>Menu</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="grid-container"></div>
<script src="script.js"></script>
</body>
</html>
js
const mqMobile = window.matchMedia("(max-width: 600px)");
const mqDesktop = window.matchMedia("(min-width: 601px)");
const gridContainer = document.querySelector(".grid-container");
function clearGrid() {
gridContainer.innerHTML = "";
}
function createSubmenuElements(submenus) {
return submenus.map((sub) => {
const submenu = document.createElement("div");
submenu.className = "submenu";
submenu.textContent = sub;
return submenu;
});
}
function renderMenus(menuData) {
clearGrid();
menuData.forEach((menus) => {
const menuContainer = document.createElement("div");
menuContainer.className = "menu-container";
menus.mainmenus.forEach((menu) => {
const menuDiv = document.createElement("div");
const mainmenu = document.createElement("div");
mainmenu.className = "mainmenu";
mainmenu.textContent = menu.title;
if (mqDesktop.matches) {
menuDiv.appendChild(mainmenu);
const submenuElements = createSubmenuElements(menu.submenus);
submenuElements.forEach((el) => menuDiv.appendChild(el));
} else {
const submenuWrapper = document.createElement("div");
submenuWrapper.style.display = "none";
const submenuElements = createSubmenuElements(menu.submenus);
submenuElements.forEach((el) => submenuWrapper.appendChild(el));
mainmenu.addEventListener("click", () => {
const isVisible = submenuWrapper.style.display === "block";
submenuWrapper.style.display = isVisible ? "none" : "block";
});
menuDiv.appendChild(mainmenu);
menuDiv.appendChild(submenuWrapper);
}
menuContainer.appendChild(menuDiv);
});
gridContainer.appendChild(menuContainer);
});
}
fetch("menudata.json")
.then((res) => res.json())
.then((menuData) => {
renderMenus(menuData);
window.addEventListener("resize", () => {
renderMenus(menuData);
});
})
.catch((error) => {
console.error("메뉴 데이터를 불러오는 데 실패했습니다:", error);
});
css
body {
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
}
.grid-container {
max-width: 1600px;
width: 100%;
gap: 16px;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
gap: 32px;
}
.menu-container {
display: flex;
flex-direction: column;
gap: 48px;
}
.mainmenu {
font-size: 14px;
}
.submenu {
font-size: 12px;
color: gray;
}
@media (max-width: 600px) {
.grid-container {
display: flex;
flex-direction: column;
justify-content: flex-start;
flex-wrap: nowrap;
gap: 0px;
}
.menu-container {
gap: 0px;
}
}
json
[
{
"mainmenus": [
{
"title": "메뉴 1",
"submenus": [
"사이드메뉴 1a",
"사이드메뉴 1b",
"사이드메뉴 1c",
"사이드메뉴 1d",
"사이드메뉴 1e",
"사이드메뉴 1f",
"사이드메뉴 1g",
"사이드메뉴 1h",
"사이드메뉴 1i",
"사이드메뉴 1j",
"사이드메뉴 1k",
"사이드메뉴 1l",
"사이드메뉴 1m",
"사이드메뉴 1n"
]
}
]
},
{
"mainmenus": [
{
"title": "메뉴 2-1",
"submenus": ["사이드메뉴 2-1a", "사이드메뉴 2-1b", "사이드메뉴 2-1c"]
},
{
"title": "메뉴 2-2",
"submenus": ["사이드메뉴 2-2a", "사이드메뉴 2-2b"]
},
{
"title": "메뉴 2-3",
"submenus": ["사이드메뉴 2-3a", "사이드메뉴 2-3b"]
}
]
},
{
"mainmenus": [
{
"title": "메뉴 3",
"submenus": [
"사이드메뉴 3a",
"사이드메뉴 3b",
"사이드메뉴 3c",
"사이드메뉴 3d",
"사이드메뉴 3e",
"사이드메뉴 3f",
"사이드메뉴 3g"
]
}
]
},
{
"mainmenus": [
{
"title": "메뉴 4-1",
"submenus": [
"사이드메뉴 4-1a",
"사이드메뉴 4-1b",
"사이드메뉴 4-1c",
"사이드메뉴 4-1d",
"사이드메뉴 4-1e"
]
},
{
"title": "메뉴 4-2",
"submenus": ["사이드메뉴 4-2a", "사이드메뉴 4-2b"]
},
{
"title": "메뉴 4-3",
"submenus": ["사이드메뉴 4-3a"]
}
]
},
{
"mainmenus": [
{
"title": "메뉴 5",
"submenus": [
"사이드메뉴 5a",
"사이드메뉴 5b",
"사이드메뉴 5c",
"사이드메뉴 5d",
"사이드메뉴 5e",
"사이드메뉴 5f",
"사이드메뉴 5g",
"사이드메뉴 5h",
"사이드메뉴 5i",
"사이드메뉴 5j",
"사이드메뉴 5k",
"사이드메뉴 5l",
"사이드메뉴 5m",
"사이드메뉴 5n"
]
}
]
}
]