Week 3 · 레이아웃과 컴포넌트 조립
Day 18 / 42
Header + Nav — 모바일 햄버거 메뉴
넓은 화면과 좁은 화면에서 메뉴가 다르게 동작해야 합니다
10초 핵심 요약
- Header는 로고와 메뉴를
justify-content: space-between으로 양 끝에 배치합니다.
- 화면이 좁아지면 메뉴를 숨기고 햄버거 버튼으로 대체합니다 — 버튼 클릭 시 JS가
.open 클래스를 토글합니다.
- 메뉴가 열렸는지 여부를 클래스 하나로만 관리하면, 상태가 헷갈릴 일이 없습니다.
01
Header 기본 구조
// src/components/Header.astro
---
const { siteName } = Astro.props;
---
<header class="site-header">
<a href="/" class="site-header__logo">{siteName}</a>
<nav class="site-header__nav">...</nav>
</header>
.site-header {
display: flex;
justify-content: space-between; /* 로고는 왼쪽 끝, 메뉴는 오른쪽 끝 */
align-items: center;
}
02
햄버거 버튼과 .open 토글 — 라이브 데모
예상해보세요 — 아래 버튼을 누르면 메뉴가 나타나야 합니다. 이 동작을 만드는 JS 코드는 몇 줄일까요?
// script.js
function toggleMenu(btn) {
const nav = document.querySelector('.site-header__nav');
const isOpen = nav.classList.toggle('open');
btn.setAttribute('aria-expanded', isOpen);
}
classList.toggle()는 클래스가 있으면 빼고 없으면 붙이는 함수입니다. 메뉴가 열려있는지 여부를 true/false 변수로 따로 저장하지 않고, .open 클래스가 있는지 없는지로만 판단합니다. CSS도 이 클래스 하나만 보고 반응합니다.
.site-header__nav { max-height: 0; overflow: hidden; transition: max-height .25s; }
.site-header__nav.open { max-height: 300px; }
03
aria-expanded — 스크린 리더를 위한 신호
aria-expanded는 화면에 보이지 않지만, 스크린 리더 사용자에게 "이 버튼을 누르면 펼쳐지는 요소가 있고, 지금 열려있는지 닫혀있는지"를 알려줍니다. 시각적으로 아무 차이가 없어도 접근성에 중요한 속성입니다.
04
Day 18 완료 체크리스트
justify-content: space-between으로 로고/메뉴를 양 끝 배치했다.
햄버거 버튼 클릭 시 .open 클래스가 토글되는 걸 확인했다.
aria-expanded 속성의 목적을 설명할 수 있다.
스스로 설명해보기 — 메뉴가 열렸는지 여부를 변수 대신 .open 클래스로 관리하는 이유를 설명할 수 있나요?
오늘의 용어
justify-content: space-between
자식 요소들을 양 끝으로 밀어 배치하는 Flex 속성
classList.toggle()
클래스가 있으면 제거, 없으면 추가하는 JS 메서드
aria-expanded
접힘/펼침 상태를 스크린 리더에 알리는 접근성 속성