Mục lục
- Khi nào nên dùng công tắc
- Tiêu chí UX/UI quan trọng
- Cấu trúc HTML tối giản (khuyến nghị)
- Demo
- CSS tạo kiểu hiện đại (mượt như app)
- Hiển thị nhãn On/Off khi cần
- Trạng thái disabled và lỗi
- Đồng bộ state bằng JavaScript khi cần
- Hỗ trợ dark mode và giảm chuyển động
- Biến thể kích thước nhanh
- Khả năng truy cập chuẩn
- Checklist kiểm thử nhanh
Khi nào nên dùng công tắc
- Thiết lập bật/tắt áp dụng ngay (không cần nút Lưu).
- Tùy chọn nhị phân rõ ràng, không gây mơ hồ như radio/checkbox nhiều lựa chọn.
- Hành động không phá vỡ ngữ cảnh (không điều hướng sang trang khác).
Tiêu chí UX/UI quan trọng
- Phản hồi tức thì: trạng thái, màu sắc, chuyển động nhẹ.
- Hit area đủ lớn: tối thiểu 40×24px.
- Khả năng truy cập: điều khiển bằng bàn phím, hỗ trợ trình đọc màn hình.
- Trạng thái đầy đủ: on, off, focus, hover, disabled, loading.
Cấu trúc HTML tối giản (khuyến nghị)
Sử dụng <input type="checkbox"> để giữ hành vi mặc định tốt cho bàn phím và truy cập. Ẩn thị giác, nhưng vẫn còn trong cây truy cập.
<div class="toggle">
<input
class="toggle__input"
type="checkbox"
id="notify"
aria-label="Bật thông báo"
/>
<label class="toggle__track" for="notify"><span class="toggle__thumb"></span></label>
</div>
Demo
CSS tạo kiểu hiện đại (mượt như app)
.toggle {
--w: 46px;
--h: 26px;
--p: 3px;
--bg-off: #d1d5db;
--bg-on: #22c55e;
--thumb: #fff;
--ring: 0 0 0 3px rgba(34,197,94,.25);
display: inline-flex;
align-items: center;
}
.toggle__input {
position: absolute;
width: 1px; height: 1px;
margin: -1px; border: 0; padding: 0;
clip: rect(0 0 0 0); clip-path: inset(50%);
overflow: hidden; white-space: nowrap;
}
.toggle__track {
position: relative;
display: inline-block;
width: var(--w); height: var(--h);
background: var(--bg-off);
border-radius: var(--h);
cursor: pointer;
transition: background-color .18s ease, box-shadow .18s ease;
box-shadow: inset 0 1px 2px rgba(0,0,0,.06);
}
.toggle__thumb {
position: absolute;
top: var(--p); left: var(--p);
width: calc(var(--h) - var(--p)*2);
height: calc(var(--h) - var(--p)*2);
background: var(--thumb);
border-radius: 50%;
box-shadow: 0 1px 2px rgba(0,0,0,.15), 0 3px 6px rgba(0,0,0,.12);
transition: transform .18s ease;
}
.toggle__input:checked + .toggle__track {
background: var(--bg-on);
}
.toggle__input:checked + .toggle__track .toggle__thumb {
transform: translateX(calc(var(--w) - var(--h)));
}
.toggle__track:hover { filter: brightness(0.98); }
.toggle__input:focus-visible + .toggle__track { box-shadow: var(--ring); }
.toggle__input:disabled + .toggle__track {
cursor: not-allowed;
filter: grayscale(30%); opacity: .7;
}
Hiển thị nhãn On/Off khi cần
<div class="toggle toggle--labeled">
<input class="toggle__input" type="checkbox" id="darkmode" aria-labelledby="darkmode-label" />
<label class="toggle__track" for="darkmode"><span class="toggle__thumb"></span></label>
<span id="darkmode-label" class="toggle__label">Giao diện tối</span>
</div>
<style>
.toggle--labeled { gap: .5rem; vertical-align: middle; }
.toggle__label { font-size: 14px; line-height: 1; user-select: none; }
</style>
Trạng thái disabled và lỗi
.toggle--error .toggle__track { background: #fecaca; }
.toggle--error .toggle__input:checked + .toggle__track { background: #ef4444; }
Đồng bộ state bằng JavaScript khi cần
<script>
document.addEventListener('change', function(e) {
const el = e.target;
if (!el.classList.contains('toggle__input')) return;
const track = el.nextElementSibling;
track.style.filter = 'brightness(0.9)';
setTimeout(() => track.style.filter = '', 120);
});
</script>
Hỗ trợ dark mode và giảm chuyển động
@media (prefers-color-scheme: dark) {
.toggle__track { background: #374151; }
.toggle__input:checked + .toggle__track { background: #10b981; }
}
@media (prefers-reduced-motion: reduce) {
.toggle__track, .toggle__thumb { transition: none; }
}
Biến thể kích thước nhanh
.toggle--sm { --w: 38px; --h: 22px; --p: 3px; }
.toggle--lg { --w: 56px; --h: 32px; --p: 4px; }
Khả năng truy cập chuẩn
- Sử dụng input checkbox thật.
- Dùng aria-label hoặc aria-labelledby.
- Focus rõ ràng với :focus-visible.
- Không cần role=”switch” nếu dùng input checkbox.
Checklist kiểm thử nhanh
- Click và phím Space/Enter đều bật tắt được.
- Tương phản màu đủ mạnh.
- Disabled thể hiện rõ ràng.
- Hoạt động tốt trên dark mode.
Bình luận