토글 스위치

Toggle switch

켜짐/꺼짐 두 상태를 손잡이가 좌우로 미끄러지며 누르는 즉시 전환하는 컨트롤.

다른 이름: SwitchOn/off switch
···
html
<div class="rows">
  <div class="row"><span>알림</span><button class="sw" id="s1" role="switch" aria-checked="true"><i></i></button></div>
  <div class="row"><span>자동저장</span><button class="sw" id="s2" role="switch" aria-checked="false"><i></i></button></div>
  <div class="row"><span>공개 프로필</span><button class="sw" id="s3" role="switch" aria-checked="true"><i></i></button></div>
</div>
css
.rows{display:grid;gap:12px;width:min(200px,88%)}
.row{display:flex;justify-content:space-between;align-items:center;font-size:13px;color:var(--fg)}
.sw{width:42px;height:24px;border-radius:999px;border:1px solid var(--line);background:var(--line);position:relative;cursor:pointer;padding:0;transition:background .2s}
.sw[aria-checked=true]{background:var(--accent);border-color:var(--accent)}
.sw i{position:absolute;top:2px;left:2px;width:18px;height:18px;border-radius:50%;background:#fff;transition:transform .2s;box-shadow:0 1px 3px rgba(0,0,0,.3)}
.sw[aria-checked=true] i{transform:translateX(18px)}
js
const sws = [...document.querySelectorAll('.sw')];
function flip(s) { s.setAttribute('aria-checked', String(s.getAttribute('aria-checked') !== 'true')); }
let auto = true;
sws.forEach((s) => s.addEventListener('click', () => { auto = false; flip(s); }));
sws.forEach((s, i) => setInterval(() => { if (auto) flip(s); }, 1600 + i * 500));

role="switch"와 aria-checked를 쓰거나, <input type="checkbox">를 시각적으로만 스위치처럼 꾸밉니다(의미는 그대로 checkbox이므로 스크린리더 호환성이 더 좋습니다). 상태를 색으로만 표시하지 말고 "켜짐/꺼짐" 텍스트나 아이콘을 옆에 두면 색맹 사용자도 알 수 있습니다.

체크박스와 목적이 다릅니다. 체크박스는 보통 "저장" 버튼을 눌러야 반영되는 다중 선택 항목이지만, 스위치는 누르는 즉시 실제 설정에 적용되는 단일 이진 값입니다 — 비행기 모드, 다크 모드처럼요. 그래서 스위치 옆에는 "저장" 버튼을 두지 않는 게 관례입니다.

폼 제출과 무관하게 즉시 서버에 반영되는 스위치는 실패했을 때(네트워크 오류 등) 원래 상태로 되돌리는 처리가 꼭 필요합니다.