모바일 화면에서 ☰ 아이콘 한 번에 열리는 그 네비게이션.
원리부터 슬라이드·드롭다운·X자 애니메이션까지 — 복붙 한 번에 내 사이트에 바로 적용해요.
세 줄짜리 아이콘(☰) 뒤에 숨겨진 네비게이션 — 모바일 UI의 핵심 패턴
모바일 앱이나 웹사이트 상단 구석에 줄 세 개짜리 아이콘(☰)을 눌렀을 때 메뉴가 쫙 펼쳐진 경험, 다들 있으시죠? 그게 바로 햄버거 메뉴(Hamburger Menu)예요. 세 개의 가로선이 마치 햄버거를 옆에서 본 모습처럼 생겼다고 해서 붙은 이름이에요. 위 빵 → 패티 → 아래 빵, 딱 3줄이죠.
데스크탑 화면에서는 링크들을 가로로 쭉 나열해도 충분한 공간이 있지만, 모바일 화면은 너비가 좁아서 메뉴 항목들이 다 들어가지 않아요. 그래서 768px 이하 같은 특정 너비 기준으로 메뉴를 숨기고, ☰ 버튼 하나만 보여두는 거예요. 버튼을 누르면 메뉴가 다시 나타나고, 다시 누르거나 바깥을 클릭하면 닫히죠.
구현 원리는 간단해요. CSS @media 쿼리로 작은 화면에서 일반 메뉴를 display: none으로 숨기고,
☰ 버튼을 display: flex로 보여줘요.
그 버튼을 클릭하면 JavaScript가 메뉴 요소에 open 클래스를 추가하거나 제거하고,
CSS transition이 부드러운 애니메이션을 담당해요.
좁은 모바일 화면에서 네비게이션 항목들을 하나의 아이콘 뒤에 깔끔하게 숨겨요. UX의 핵심 패턴이에요.
모바일과 데스크탑을 동시에 지원하는 반응형 웹사이트라면 햄버거 메뉴는 거의 필수 구성 요소예요.
별도 라이브러리 없이 순수 코드로 만들 수 있어요. 미디어 쿼리, 클래스 토글, 트랜지션만 알면 완성!
슬라이드, 드롭다운, 페이드인 등 열리는 방식에 따라 사이트의 분위기가 달라져요. 골라 쓰세요.
언제 햄버거 메뉴를 쓰나요? 보통 768px 이하 (태블릿·모바일) 화면에서 사용해요. 데스크탑에서는 가로 네비게이션을 그대로 보여주고, 모바일에서만 햄버거 메뉴로 전환하는 게 일반적인 패턴이에요. CSS @media (max-width: 768px)를 기준으로 스타일을 나눠요.
☰ 기호의 유니코드는 U+2630이에요. HTML에서는 ☰ 또는 그냥 ☰을 직접 입력해도 되고, 실제 프로젝트에서는 CSS로 만든 세 개의 <span> 또는 SVG 아이콘을 주로 사용해요. 코드로 만들면 열릴 때 X자(✕)로 바뀌는 애니메이션을 쉽게 추가할 수 있거든요.
어떤 스타일이 내 사이트에 어울릴까요? 직접 클릭해서 동작을 확인해보세요.
HTML 구조부터 CSS 애니메이션, JS 토글 로직까지 완전한 코드와 설명
<nav> 태그를 사용해요. 안에 로고, 데스크탑 메뉴, 햄버거 버튼을 나란히 배치해요.open 클래스를 추가/제거해요. CSS는 이 클래스의 유무로 애니메이션을 제어해요.height는 auto에서 transition이 안 돼요. 대신 max-height를 0에서 충분히 큰 값으로 변경하면 부드럽게 펼쳐져요.<!-- HTML 구조 --> <header class="site-header"> <nav class="navbar"> <!-- 로고 --> <a href="/" class="nav-logo">MySite</a> <!-- 데스크탑 + 모바일 메뉴 --> <ul class="nav-menu" id="navMenu"> <li><a href="#">홈</a></li> <li><a href="#">소개</a></li> <li><a href="#">서비스</a></li> <li><a href="#">문의하기</a></li> </ul> <!-- 햄버거 버튼 --> <button class="hamburger" id="hamburgerBtn" aria-label="메뉴 열기" aria-expanded="false" > <span class="hline"></span> <span class="hline"></span> <span class="hline"></span> </button> </nav> </header>
/* ── 기본 네비게이션 ── */ .site-header { position: fixed; top: 0; left: 0; right: 0; background: #fff; box-shadow: 0 1px 8px rgba(0,0,0,.08); z-index: 100; } .navbar { display: flex; align-items: center; justify-content: space-between; padding: 0 24px; height: 60px; } /* ── 데스크탑 메뉴 ── */ .nav-menu { display: flex; list-style: none; gap: 8px; } .nav-menu a { padding: 6px 14px; border-radius: 6px; color: #374151; font-weight: 500; text-decoration: none; transition: background .15s; } .nav-menu a:hover { background: #f3f4f6; } /* ── 햄버거 버튼 ── */ .hamburger { display: none; /* 기본은 숨김 */ flex-direction: column; gap: 5px; padding: 8px; background: none; border: none; cursor: pointer; } .hline { width: 22px; height: 2px; background: #111827; border-radius: 2px; transition: transform .3s, opacity .3s; transform-origin: center; } /* ☰ → ✕ 애니메이션 */ .hamburger.open .hline:nth-child(1) { transform: translateY(7px) rotate(45deg); } .hamburger.open .hline:nth-child(2) { opacity: 0; transform: scaleX(0); } .hamburger.open .hline:nth-child(3) { transform: translateY(-7px) rotate(-45deg); } /* ── 모바일 반응형 ── */ @media (max-width: 768px) { .hamburger { display: flex; } .nav-menu { position: absolute; top: 60px; left: 0; right: 0; flex-direction: column; background: #fff; box-shadow: 0 8px 24px rgba(0,0,0,.10); max-height: 0; overflow: hidden; transition: max-height .35s cubic-bezier(.4,0,.2,1); padding: 0; gap: 0; } .nav-menu.open { max-height: 400px; padding: 8px 0; } .nav-menu li a { display: block; padding: 12px 24px; border-radius: 0; border-bottom: 1px solid #f3f4f6; } }
// 요소 참조 const btn = document.getElementById('hamburgerBtn'); const menu = document.getElementById('navMenu'); const nav = document.querySelector('.navbar'); // 메뉴 열기 / 닫기 함수 function openMenu() { menu.classList.add('open'); btn.classList.add('open'); btn.setAttribute('aria-expanded', 'true'); btn.setAttribute('aria-label', '메뉴 닫기'); document.body.style.overflow = 'hidden'; // 스크롤 방지 } function closeMenu() { menu.classList.remove('open'); btn.classList.remove('open'); btn.setAttribute('aria-expanded', 'false'); btn.setAttribute('aria-label', '메뉴 열기'); document.body.style.overflow = ''; } // 버튼 클릭 시 토글 btn.addEventListener('click', () => { if (menu.classList.contains('open')) { closeMenu(); } else { openMenu(); } }); // 바깥 클릭 시 닫기 document.addEventListener('click', (e) => { if (!nav.contains(e.target)) { closeMenu(); } }); // 메뉴 항목 클릭 시 닫기 menu.querySelectorAll('a').forEach(link => { link.addEventListener('click', () => { closeMenu(); }); }); // ESC 키로 닫기 document.addEventListener('keydown', (e) => { if (e.key === 'Escape') closeMenu(); });
데스크탑 / 모바일 모드를 전환하면서 실제 동작을 확인해보세요.
바이브 코딩으로 햄버거 메뉴를 만들 때 이 프롬프트를 그대로 복붙하세요.
아래 프롬프트를 Claude, ChatGPT, Cursor 등 AI 코딩 도구에 붙여넣으면 바로 작동하는 코드를 받을 수 있어요. 필요에 따라 메뉴 항목이나 색상을 바꿔서 사용하세요.
내 사이트 상단 네비게이션을 모바일에서 햄버거 메뉴로 바꿔줘. 요구사항: - 768px 이하에서 기존 메뉴를 숨기고 ☰ 버튼을 보여줘 - 버튼 클릭 시 메뉴가 아래로 슬라이드되어 나타나게 해줘 (max-height 트릭 사용) - ☰ 버튼이 클릭되면 ✕ 로 바뀌는 CSS 애니메이션 추가해줘 - 메뉴 항목: 홈, 소개, 서비스, 문의하기 - 메뉴 항목 클릭 시 메뉴가 닫히게 해줘 - 바깥 영역 클릭 시 메뉴가 닫히게 해줘 - ESC 키로도 닫히게 해줘 - aria-expanded 접근성 속성도 올바르게 처리해줘
더 구체적으로 요청하면 더 좋은 코드가 나와요! "슬라이드 사이드바 방식으로 만들어줘" 또는 "왼쪽에서 밀려나오는 오버레이 패널 방식으로" 처럼 원하는 동작을 명확히 설명하면 AI가 정확히 맞춰줘요.
기존 코드가 있다면 "아래 코드에서 nav 부분을 햄버거 메뉴로 바꿔줘:"라고 시작하고 코드를 붙여넣으세요. 훨씬 정확한 결과를 받을 수 있어요.
햄버거 메뉴를 처음 만들 때 자주 마주치는 문제들을 정리했어요.
미디어 쿼리 밖에서 .hamburger { display: none; }으로 기본 숨김 처리를 먼저 해주세요. 그다음 @media (max-width: 768px) 안에서 .hamburger { display: flex; }로 모바일에서만 보이게 하면 돼요.
반대로 데스크탑 메뉴는 기본적으로 display: flex이고, 미디어 쿼리 안에서 display: none으로 숨겨야 해요. 이 두 가지를 쌍으로 처리해야 해요.
메뉴가 열릴 때 배경 스크롤을 막지 않아서 생기는 현상이에요. JavaScript에서 메뉴를 열 때 document.body.style.overflow = 'hidden'을 추가하고, 닫을 때 document.body.style.overflow = ''으로 되돌리면 해결돼요.
특히 풀스크린 드롭다운이나 사이드바 방식에서는 이 처리가 꼭 필요해요.
각 메뉴 항목(<a> 태그)에 클릭 이벤트를 달아서 closeMenu()를 호출해야 해요.
menu.querySelectorAll('a').forEach(link => link.addEventListener('click', closeMenu))처럼 모든 링크에 한 번에 처리하면 편해요. SPA(싱글 페이지 앱)에서는 라우터 변경 이벤트에서도 닫아줘야 해요.
CSS transition은 height: auto를 지원하지 않아요. 이때 사용하는 꼼수가 max-height 트릭이에요. 닫혔을 때 max-height: 0; overflow: hidden;으로 설정하고, 열렸을 때 max-height: 400px;처럼 충분히 큰 값으로 바꾸면 부드럽게 펼쳐져요.
단, max-height 값이 실제 내용보다 훨씬 크면 닫힐 때 먼저 줄어들고 나중에 사라지는 느낌이 날 수 있으니, 내용 높이와 너무 차이나지 않게 설정하세요.
헤더에 position: fixed; top: 0; left: 0; right: 0;를 적용해야 해요. 그리고 <body>에 padding-top: 60px;(헤더 높이만큼)을 추가해야 헤더 뒤에 콘텐츠가 가려지지 않아요.
네, 꼭 챙겨야 해요. 햄버거 버튼에 aria-label="메뉴 열기"와 aria-expanded="false"를 추가하고, 메뉴가 열리면 aria-expanded="true"로 업데이트해요. 또한 ESC 키로 닫히도록 처리하면 키보드 사용자도 불편 없이 이용할 수 있어요.
버튼에 <button> 태그를 사용하면 키보드 포커스가 자동으로 처리되니, <div>나 <span>이 아닌 <button>을 쓰는 것을 권장해요.