이번 편의 결과물: 내비게이션 메뉴 항목이 데스크톱 폭에서 가로로 정렬됩니다. 다루는 개념: flex container/item, justify-content/align-items, gap
이 편에서 만드는 파일
web-practice/portfolio/
└── css/
└── styles.css ~ (.site-nav Flexbox 규칙 추가)개념 정리
Flexbox는 display: flex를 지정한 요소(flex container)의 자식들(flex item)을 한 방향(메인 축)으로 배치하는 1차원 레이아웃입니다. .site-nav는 <nav> 안에 <a> 3개(소개·프로젝트·연락)를 직접 담고 있으며, 기본 상태에서는 <a>가 인라인 요소라 옆으로 붙어 보이긴 하지만 줄바꿈 없이 정렬되지는 않습니다.
| 속성 | 적용 대상 | 역할 |
|---|---|---|
display: flex | container(.site-nav) | 자식을 flex item으로 전환, 기본 방향은 가로(row) |
justify-content | container | 메인 축(가로) 정렬. flex-start/center/space-between 등 |
align-items | container | 크로스 축(세로) 정렬. 내비 항목 높이를 맞출 때 사용 |
gap | container | item 사이 간격. margin보다 간단하고 마진 상쇄가 없다 |
흔한 오해는 justify-content를 item에 지정하는 것입니다. 정렬 속성은 항상 container(부모)에 지정합니다. item에는 flex-grow·flex-shrink·align-self처럼 자기 자신의 크기·정렬을 조정하는 속성만 씁니다.
실습
1. 마크업 확인
index.html(다른 두 페이지도 동일)의 헤더 구조는 다음과 같습니다(마크업은 수정하지 않고 확인만 합니다).
<!-- web-practice/portfolio/index.html (헤더 부분 발췌, 수정하지 않음) -->
<header class="site-header">
<a class="logo" href="index.html">Zeno Kim</a>
<nav class="site-nav">
<a href="index.html" aria-current="page">소개</a>
<a href="projects.html">프로젝트</a>
<a href="contact.html">연락</a>
</nav>
</header><nav class="site-nav"> 안에는 <ul>·<li> 없이 <a> 3개가 바로 들어 있습니다. flex container로 만들 대상은 이 <a>들의 직계 부모인 .site-nav 자체입니다.
2. styles.css 열기
07편 여백 규칙 아래에 이어서 작성합니다.
3. .site-nav를 flex container로 전환
/* web-practice/portfolio/css/styles.css */
/* ...03~07편 리셋·타이포그래피·색·여백 유지... */
.site-nav {
display: flex;
gap: var(--space-6);
}
.site-nav a {
color: var(--color-text);
font-weight: 500;
text-decoration: none;
}
.site-nav a[aria-current='page'] {
color: var(--color-primary);
font-weight: 700;
}.site-nav의 자식이 <a>뿐이므로 flex container도 .site-nav 자체에 지정합니다(<ul>이 없으니 list-style 제거는 필요 없습니다). aria-current="page"는 마크업에 이미 있는 접근성 속성으로, 현재 페이지 링크를 시각적으로도 구분하는 데 그대로 활용합니다.
4. 헤더 전체를 가로 배치로 정리
.site-header 자체도 로고와 내비를 양 끝으로 배치해야 합니다.
.site-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 var(--space-6);
height: var(--header-height);
}justify-content: space-between은 첫 item(로고)과 마지막 item(내비)을 양 끝에 붙이고 그 사이 공간을 균등하게 벌립니다. align-items: center는 로고와 내비 항목의 세로 중앙을 맞춥니다.
5. 실행
파일을 저장하고 세 페이지를 모두 브라우저로 새로고침합니다.
6. 확인
- 로고 “Zeno Kim”이 왼쪽, 내비 메뉴 3개(소개·프로젝트·연락)가 오른쪽에 가로로 나란히 보입니다.
- 메뉴 항목 사이 간격이
--space-6(1.5rem)만큼 일정합니다. - 현재 열려 있는 페이지의 메뉴 링크만 파란색(
--color-primary)과 굵은 글씨로 구분됩니다. - 개발자 도구에서
.site-nav를 선택하면 Layout 탭(Chrome 기준)에 파란 flex 배지가 표시되고, 자식<a>3개에 노란 flex item 표시가 뜹니다.
직접 해보기
.site-nav의gap을var(--space-2)로 줄여 메뉴 항목이 얼마나 촘촘해지는지 비교해 보세요..site-header의justify-content를space-between에서flex-end로 바꿔, 로고와 내비가 모두 오른쪽으로 몰리는 모습을 확인해 보세요. 확인 후space-between으로 되돌립니다.
정답 확인
gap: var(--space-2)(0.5rem)로 바꾸면 메뉴 항목 사이가 좁아져 세 링크가 서로 가까이 붙습니다. 시안 값인--space-6과 비교하면 답답해 보이므로 원래 값이 왜 선택됐는지 감이 옵니다.flex-end는 모든 item을 메인 축 끝(오른쪽)으로 모읍니다. 로고까지 오른쪽으로 밀려 헤더 왼쪽이 비어 보이므로, 로고와 내비를 양 끝에 고정하려면space-between이 맞는 선택입니다.
자주 하는 실수
| 증상 | 원인 | 고치는 법 |
|---|---|---|
| 메뉴가 옆으로 안 붙는다 | display: flex를 .site-nav가 아니라 다른 요소에 줬다 | flex container를 <a> 3개의 직계 부모인 .site-nav에 지정 |
| justify-content가 안 먹는다 | container가 아니라 item(a)에 지정했다 | 정렬 속성은 항상 부모(container)에 지정 |
| 메뉴 항목 사이 간격이 짝이 안 맞는다 | gap 대신 margin-right를 각 항목에 줘서 마지막 항목에도 여백이 남았다 | gap을 쓰면 item 사이에만 간격이 생겨 마지막 항목 뒤에는 여백이 남지 않는다 |
| 헤더 높이가 시안보다 낮다 | --header-height를 padding에만 의존해 계산했다 | height: var(--header-height)를 직접 지정하고 align-items: center로 내용만 세로 중앙 정렬 |