접이식 사이드바

Collapsible sidebar

라벨이 보이는 넓은 사이드바와 아이콘만 남는 좁은 레일 사이를 토글 버튼으로 오가는 패널.

다른 이름: Collapsible navExpandable sidebar
···
html
<div class="csw" id="csw">
  <nav class="csnav" id="csnav" aria-label="주요 메뉴">
    <button class="cstoggle" id="cstoggle" aria-expanded="true" aria-controls="csnav" aria-label="사이드바 접기">«</button>
    <a href="#" aria-current="page"><i>⌂</i><span>홈</span></a>
    <a href="#"><i>⌕</i><span>검색</span></a>
    <a href="#"><i>☺</i><span>내 정보</span></a>
  </nav>
  <div class="cscontent"><div class="csbar" style="width:70%"></div><div class="csbar" style="width:44%"></div></div>
</div>
css
.csw{position:absolute;inset:0;display:flex}
.csnav{width:120px;background:var(--surface);border-right:1px solid var(--line);display:flex;flex-direction:column;gap:4px;padding:8px;transition:width .28s ease;flex:none}
.csw[data-collapsed] .csnav{width:44px}
.cstoggle{align-self:flex-end;width:24px;height:24px;border:0;background:none;color:var(--muted);font-size:11px;cursor:default;margin-bottom:6px;transition:transform .28s}
.csw[data-collapsed] .cstoggle{transform:rotate(180deg)}
.csnav a{display:flex;align-items:center;gap:9px;padding:7px 8px;border-radius:7px;color:var(--muted);text-decoration:none;font-size:11px;white-space:nowrap;overflow:hidden}
.csnav a[aria-current]{background:color-mix(in srgb, var(--accent) 14%, transparent);color:var(--accent)}
.csnav a i{font-style:normal;width:16px;text-align:center;flex:none}
.csnav a span{transition:opacity .28s}
.csw[data-collapsed] .csnav a span{opacity:0}
.cscontent{flex:1;padding:14px;display:grid;gap:9px;align-content:start}
.csbar{height:9px;border-radius:5px;background:var(--line)}
js
const wrap = document.getElementById('csw'), toggle = document.getElementById('cstoggle');
function setCollapsed(v) {
  wrap.toggleAttribute('data-collapsed', v);
  toggle.setAttribute('aria-expanded', String(!v));
  toggle.setAttribute('aria-label', v ? '사이드바 펼치기' : '사이드바 접기');
}
let auto = true;
toggle.addEventListener('click', () => { auto = false; setCollapsed(!wrap.hasAttribute('data-collapsed')); });
setTimeout(() => {
  setInterval(() => { if (!auto) return; setCollapsed(!wrap.hasAttribute('data-collapsed')); }, 2200);
}, 2600);

접힌 상태에서도 <nav> 랜드마크와 링크 자체는 그대로 DOM에 남아 있어야 합니다 — 라벨 텍스트가 시각적으로 사라져도 각 링크는 aria-label이나 title로 접근 가능한 이름을 계속 가져야 스크린리더 사용자가 항목을 잃지 않습니다. 토글 버튼에는 aria-expanded와 aria-controls로 지금 상태와 무엇을 조절하는지를 알립니다.

내비게이션 레일(이 사전의 다른 항목)과 다른 점은 상태 전환 여부입니다 — 레일은 처음부터 끝까지 아이콘 전용의 좁은 폭으로 고정된 별개의 컴포넌트지만, 접이식 사이드바는 "라벨 있는 넓은 상태"와 "아이콘만 있는 좁은 상태"를 같은 패널이 오가는 것입니다. 결과적으로 접힌 모습이 레일과 비슷해 보일 수 있지만 하나는 고정, 하나는 토글 가능이라는 점이 다릅니다. 햄버거 메뉴·드로어와도 다릅니다 — 그쪽은 모바일에서 패널을 화면 밖으로 완전히 숨겼다 꺼내는 방식이지만, 접이식 사이드바는 데스크톱에서 패널이 사라지지 않고 계속 보이는 채로 폭만 줄어듭니다.

너비가 바뀔 때 transition으로 부드럽게 전환하면 갑자기 레이아웃이 튀는 느낌을 줄일 수 있습니다.