하단 내비게이션

Bottom navigation

모바일 화면 아래 고정돼 3~5개의 주요 화면을 아이콘과 라벨로 오가는 내비게이션 바.

다른 이름: Bottom tab barTab bar (mobile)
···
html
<div class="phone">
  <div class="pcontent"><div class="pbar" style="width:60%"></div><div class="pbar" style="width:82%"></div></div>
  <nav class="bn" aria-label="주요 메뉴" id="bn">
    <button aria-current="page"><i>⌂</i>홈</button>
    <button><i>⌕</i>검색</button>
    <button><i>♡</i>찜</button>
    <button><i>☺</i>마이</button>
  </nav>
</div>
css
.phone{width:min(190px,80%);height:100%;max-height:170px;background:var(--surface);border:1px solid var(--line);border-radius:16px;overflow:hidden;display:flex;flex-direction:column}
.pcontent{flex:1;padding:14px;display:grid;gap:8px;align-content:start}
.pbar{height:8px;border-radius:4px;background:var(--line)}
.bn{display:flex;border-top:1px solid var(--line);background:var(--bg)}
.bn button{flex:1;border:0;background:none;display:grid;place-items:center;gap:2px;padding:8px 0;font-size:9px;color:var(--muted);cursor:pointer}
.bn button i{font-style:normal;font-size:15px}
.bn button[aria-current]{color:var(--accent)}
js
const btns = [...document.querySelectorAll('.bn button')];
let auto = true, i = 0;
btns.forEach((b, idx) => b.addEventListener('click', () => { auto = false; i = idx; btns.forEach((x, xi) => xi === idx ? x.setAttribute('aria-current', 'page') : x.removeAttribute('aria-current')); }));
setInterval(() => {
  if (!auto) return;
  i = (i + 1) % btns.length;
  btns.forEach((x, xi) => xi === i ? x.setAttribute('aria-current', 'page') : x.removeAttribute('aria-current'));
}, 1500);

nav 안에 링크(또는 버튼) 목록을 두고, 현재 화면에 aria-current="page"를 줍니다. 아이콘만으로는 의미가 불분명하니 라벨 텍스트를 함께 두는 게 원칙이고, 라벨을 감춘다면 각 항목에 접근 가능한 이름을 별도로 제공해야 합니다.

내비게이션 레일과의 차이는 화면 크기와 방향입니다 — 하단 내비게이션은 엄지가 닿기 쉬운 모바일 화면 아래에 가로로 배치되고, 레일은 태블릿·데스크톱처럼 넓은 화면 측면에 세로로 붙습니다. 탭과의 차이는 무엇을 바꾸느냐입니다 — 탭은 한 페이지 안의 콘텐츠 섹션을 바꾸지만, 하단 내비게이션은 앱의 최상위 화면 자체(홈, 검색, 마이페이지 등)를 전환합니다.

항목이 5개를 넘으면 좁은 화면에서 라벨이 겹치니 보통 4~5개로 제한하고 나머지는 "더보기"로 묶습니다.