크기 조절 패널

Resizable panels

두 영역 사이의 드래그 가능한 구분선으로 사용자가 직접 비율을 조절하는 레이아웃.

다른 이름: Split viewSplit paneWindow splitter
···
html
<div class="rpw" id="rpw">
  <div class="rppane" id="rpa">사이드바</div>
  <div class="rpdiv" id="rpdiv" role="separator" aria-orientation="vertical" aria-valuenow="32" aria-valuemin="15" aria-valuemax="70" aria-label="패널 크기 조절" tabindex="0"></div>
  <div class="rppane" id="rpb">본문 콘텐츠</div>
</div>
css
.rpw{position:absolute;inset:10px;display:flex;border:1px solid var(--line);border-radius:10px;overflow:hidden}
.rppane{background:var(--surface);display:grid;place-items:center;color:var(--muted);font-size:11px;font-weight:600}
#rpa{width:32%;background:var(--bg)}
#rpb{flex:1}
.rpdiv{width:6px;background:var(--line);cursor:col-resize;position:relative;flex:none}
.rpdiv::after{content:"";position:absolute;top:50%;left:50%;width:2px;height:18px;background:var(--muted);transform:translate(-50%,-50%);border-radius:2px}
.rpdiv:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
js
const wrap = document.getElementById('rpw'), a = document.getElementById('rpa'), div = document.getElementById('rpdiv');
function setPct(pct) {
  pct = Math.max(15, Math.min(70, pct));
  a.style.width = pct + '%';
  div.setAttribute('aria-valuenow', String(Math.round(pct)));
}
let auto = true, dragging = false;
div.addEventListener('pointerdown', (e) => { auto = false; dragging = true; div.setPointerCapture(e.pointerId); });
div.addEventListener('pointermove', (e) => {
  if (!dragging) return;
  const rect = wrap.getBoundingClientRect();
  setPct(((e.clientX - rect.left) / rect.width) * 100);
});
div.addEventListener('pointerup', () => { dragging = false; });
div.addEventListener('keydown', (e) => {
  if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return;
  auto = false; e.preventDefault();
  const cur = parseFloat(div.getAttribute('aria-valuenow'));
  setPct(cur + (e.key === 'ArrowRight' ? 4 : -4));
});
let pct = 32, dir = 1;
setInterval(() => {
  if (!auto) return;
  pct += dir * 3;
  if (pct >= 55) dir = -1;
  if (pct <= 22) dir = 1;
  setPct(pct);
}, 260);

구분선(divider/splitter)에는 role="separator"와 aria-orientation, 그리고 지금 비율을 나타내는 aria-valuenow/min/max를 두어 스크린리더가 "지금 32%" 같은 값을 읽게 합니다. 마우스로는 드래그, 키보드로는 초점이 구분선에 있을 때 방향키로 일정 단위씩 조절하는 게 관례입니다.

브레이크포인트(layout 카테고리)가 화면 크기 구간마다 미리 정한 고정 레이아웃으로 전환하는 것과 달리, 크기 조절 패널은 같은 화면 크기 안에서도 사용자가 실시간으로 원하는 비율을 정합니다 — 코드 에디터의 파일 탐색기 폭, 메일 클라이언트의 목록/본문 비율처럼 사람마다 선호가 다른 화면에 잘 맞습니다.

각 패널에는 min-width(또는 %)로 하한을 둬야 구분선을 한쪽 끝까지 끌었을 때 패널이 완전히 찌그러지거나 사라지는 걸 막을 수 있습니다.