Tấn Phát Digital

Toggle Switch CSS - Tạo Công Tắc Bật Tắt Chuẩn Truy Cập

Tạo công tắc bật/tắt dựa trên checkbox thật có role="switch": dùng được bằng bàn phím, trình đọc màn hình đọc đúng trạng thái, có viền focus, chế độ giảm chuyển động và tương phản cao. Chỉnh kích thước, màu, núm, chữ ON/OFF rồi sao chép HTML, CSS.

Tùy chỉnh

Kích thước thực tế: rãnh 52 x 30px, núm 24px, quãng trượt 22px.

Các phần con đặt tên theo kiểu BEM: switch__input, switch__track, switch__label.

Xem thử

Trạng thái đọc bằng JavaScript: Đang bật

Bấm vào công tắc hoặc nhãn để đổi trạng thái. Dùng phím Tab để đưa focus tới công tắc, phím Space để bật tắt như checkbox thông thường.

Tương phản phi văn bản (WCAG 1.4.11)
  • Núm so với rãnh khi tắt4,83:1 đạt
  • Núm so với rãnh khi bật5,02:1 đạt
  • Rãnh khi tắt so với nền trang4,83:1 đạt
  • Rãnh khi bật so với nền trang5,02:1 đạt
  • Viền focus so với nền trang5,17:1 đạt

Công tắc cần nhận ra được ranh giới và vị trí núm, nên các cặp màu trên nên đạt 3:1. Chữ ON/OFF là văn bản nhỏ nên cần 4,5:1. Đây là gợi ý để kiểm tra, không phải kết luận thay cho kiểm thử với người dùng.

Mã nguồn

HTML

<label class="switch">
  <input class="switch__input" type="checkbox" role="switch" name="thong_bao" value="1">
  <span class="switch__track" aria-hidden="true"></span>
  <span class="switch__label">Nhận thông báo qua email</span>
</label>

CSS

.switch {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  position: relative;
  cursor: pointer;
}

/* Ô checkbox thật vẫn nằm trong trang để bàn phím và trình đọc màn hình dùng được, chỉ ẩn đi về mặt hình ảnh */
.switch__input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
}

.switch__track {
  position: relative;
  flex: none;
  width: 52px;
  height: 30px;
  border-radius: 15px;
  background-color: #6b7280;
  transition: background-color 200ms ease;
}

.switch__track::before {
  content: "";
  position: absolute;
  top: 3px;
  inset-inline-start: 3px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background-color: #ffffff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
  transition: transform 200ms ease;
}

.switch__input:checked + .switch__track {
  background-color: #15803d;
}

.switch__input:checked + .switch__track::before {
  transform: translateX(22px);
}

/* Trang viết từ phải sang trái: núm bắt đầu ở bên phải và trượt sang trái */
[dir="rtl"] .switch__input:checked + .switch__track::before {
  transform: translateX(-22px);
}

.switch__input:focus-visible + .switch__track {
  outline: 2px solid #2563eb;
  outline-offset: 2px;
}

.switch__input:disabled + .switch__track {
  opacity: 0.5;
}

.switch__input:disabled ~ * {
  cursor: not-allowed;
}

@media (prefers-reduced-motion: reduce) {
  .switch__track,
  .switch__track::before {
    transition: none;
  }
}

/* Chế độ tương phản cao của Windows: dùng màu hệ thống để công tắc không biến mất */
@media (forced-colors: active) {
  .switch__track,
  .switch__track::before {
    forced-color-adjust: none;
  }

  .switch__track {
    background-color: Canvas;
    outline: 1px solid CanvasText;
  }

  .switch__track::before {
    background-color: CanvasText;
  }

  .switch__input:checked + .switch__track {
    background-color: Highlight;
  }

  .switch__input:checked + .switch__track::before {
    background-color: HighlightText;
  }
}

JavaScript

const toggle = document.querySelector(".switch__input");

// Đọc trạng thái mỗi khi người dùng bật hoặc tắt
toggle.addEventListener("change", () => {
  console.log(toggle.checked ? "Đang bật" : "Đang tắt");
});

// Đặt trạng thái bằng mã (không phát sinh sự kiện change)
toggle.checked = true;

Hợp tác ngay với Tấn Phát Digital

Chúng tôi không chỉ thiết kế website, mà còn giúp doanh nghiệp xây dựng thương hiệu số mạnh mẽ. Cung cấp dịch vụ thiết kế website trọn gói từ thiết kế đến tối ưu SEO. Hãy liên hệ ngay với Tấn Phát Digital để cùng tạo nên những giải pháp công nghệ đột phá, hiệu quả và bền vững cho doanh nghiệp của bạn tại Hồ Chí Minh.

Toggle switch CSS dựng trên checkbox thật, dùng được bằng bàn phím và trình đọc màn hình

Công tắc bật/tắt xuất hiện ở khắp nơi: bật thông báo, chế độ tối, tự động gia hạn. Nhiều mẫu toggle switch CSS trên mạng chỉ là một thẻ div đổi màu khi bấm, không nhận focus bằng phím Tab và trình đọc màn hình không biết nó đang bật hay tắt. Công cụ này tạo công tắc dựa trên input type="checkbox" có role="switch", bạn chỉnh kích thước, màu, núm, chữ ON/OFF và chuyển động, rồi sao chép HTML, CSS cùng đoạn JavaScript đọc trạng thái.

Tính năng nổi bật

  • Công tắc dựng trên checkbox thật với role="switch": nhận focus bằng Tab, bật tắt bằng phím Space, gửi được trong form
  • Chỉnh chiều rộng, chiều cao, khoảng hở quanh núm, bo góc rãnh, bo góc núm; công cụ tự tính kích thước núm và quãng trượt
  • Màu rãnh khi tắt, khi bật, màu núm, bóng dưới núm, màu viền focus; chữ ON/OFF tùy chọn với màu riêng
  • Ba kiểu chuyển động: mượt, đều, nảy nhẹ cuối hành trình; thời gian trượt từ 0 đến 800 ms
  • Viền focus-visible, kiểu vô hiệu, khối prefers-reduced-motion và khối forced-colors cho chế độ tương phản cao của Windows
  • Hỗ trợ trang viết từ phải sang trái: núm dùng inset-inline-start và có luật riêng cho dir="rtl", xem thử được ngay
  • Đo tương phản phi văn bản giữa núm và rãnh, rãnh và nền trang, viền focus và nền trang theo ngưỡng 3:1
  • Năm mẫu có sẵn và đặt tên class gốc theo kiểu BEM, sao chép riêng HTML, CSS và JavaScript

Vì sao nên dùng công tắc dựng trên checkbox thay vì div

Thẻ input type="checkbox" đã có sẵn mọi thứ một công tắc cần: nhận focus, bật tắt bằng phím Space, có trạng thái checked mà JavaScript và form đọc được, và được trình đọc màn hình hiểu. Thêm role="switch" để công nghệ hỗ trợ đọc là công tắc bật hoặc tắt thay vì ô đánh dấu. Phần hình ảnh chỉ là một thẻ span đứng ngay sau input, được tạo kiểu theo trạng thái :checked và :focus-visible của input. Cách làm này không cần JavaScript để hoạt động, hỏng CSS thì vẫn còn một checkbox dùng được, và bạn không phải tự viết lại xử lý bàn phím như khi dùng div.

Lợi ích khi sử dụng

  • Dùng được bằng bàn phím mà không cần viết JavaScript
  • Trình đọc màn hình đọc đúng trạng thái bật hoặc tắt
  • Gửi được trong form như một checkbox bình thường
  • Không biến mất trong chế độ tương phản cao của Windows
  • Chạy đúng chiều trên trang tiếng Ả Rập, tiếng Do Thái
  • Tạo và xem thử ngay trên trình duyệt, không cần đăng ký

Cách tạo toggle switch CSS

  1. 1Chọn mẫu: Bấm iOS, Material, Vuông có chữ, Nhỏ gọn hoặc Nảy để có điểm xuất phát.
  2. 2Chỉnh kích thước: Kéo chiều rộng, chiều cao, khoảng hở quanh núm và bo góc. Dòng Kích thước thực tế cho biết núm to bao nhiêu và trượt bao xa.
  3. 3Chỉnh màu và chữ: Chọn màu rãnh khi tắt, khi bật, màu núm, màu viền focus. Bật Hiện chữ ON/OFF nếu muốn có chữ trên rãnh và nhập chữ tùy ý.
  4. 4Kiểm tra: Bấm công tắc trong ô Xem thử, dùng Tab và Space để thử bằng bàn phím, bật Xem hướng phải sang trái, và xem bảng tương phản.
  5. 5Sao chép mã: Đổi nhãn và tên class nếu cần, rồi sao chép HTML, CSS và đoạn JavaScript đọc trạng thái.

Cấu trúc HTML của công tắc

Mã gồm một thẻ label bao ngoài, bên trong là input checkbox có role="switch", một thẻ span làm rãnh có aria-hidden="true" và một thẻ span chứa nhãn. Vì mọi thứ nằm trong label, bấm vào chữ cũng bật tắt được công tắc, vùng bấm rộng hơn và dễ dùng trên điện thoại. Input được ẩn về mặt hình ảnh bằng opacity: 0 và kích thước 1px nhưng vẫn nằm trong trang, nên vẫn nhận focus và vẫn được trình đọc màn hình đọc. Thứ tự input đứng ngay trước rãnh là bắt buộc, vì CSS dùng bộ chọn anh em liền kề + để đổi màu rãnh theo trạng thái của input. Khi chọn Nhãn đứng trước công tắc, công cụ đưa thẻ nhãn lên đầu nhưng vẫn giữ nguyên cặp input và rãnh.

role="switch" khác gì checkbox thường

Về hành vi, hai thứ giống hệt nhau: bấm hoặc nhấn Space để đổi trạng thái, giá trị nằm ở thuộc tính checked. Khác biệt nằm ở cách công nghệ hỗ trợ gọi tên. Checkbox được đọc là đã chọn hoặc chưa chọn, hợp với việc chọn một mục trong danh sách. Switch được đọc là bật hoặc tắt, hợp với thiết lập có hiệu lực ngay như bật thông báo. Nếu thay đổi chỉ có hiệu lực khi bấm nút Lưu, một checkbox bình thường có khi còn rõ nghĩa hơn. Lưu ý khác: như mọi checkbox, công tắc này không bật tắt bằng phím Enter, chỉ bằng Space.

Đọc và đặt trạng thái bằng JavaScript

Vì là checkbox thật, bạn đọc trạng thái qua thuộc tính checked và lắng nghe sự kiện change, đúng như đoạn mã công cụ xuất ra. Đặt toggle.checked = true bằng mã sẽ đổi giao diện ngay nhưng không phát sinh sự kiện change, nên nếu có xử lý đi kèm, hãy gọi hàm xử lý trực tiếp. Trong form, input có name="thong_bao" và value="1": khi bật, form gửi thong_bao=1, khi tắt, trường này không được gửi đi, giống mọi checkbox. Trong React, dùng checked cùng onChange để điều khiển, hoặc defaultChecked nếu không cần kiểm soát trạng thái.

Trang viết từ phải sang trái

Với tiếng Ả Rập, tiếng Do Thái, người dùng quen với công tắc có núm nằm bên phải khi tắt và trượt sang trái khi bật. Mã của công cụ đặt núm bằng inset-inline-start, thuộc tính logic tự đổi bên theo hướng viết, nên vị trí tắt đúng ngay mà không cần thêm luật. Riêng phép dịch transform: translateX() không tự đổi chiều, vì vậy có thêm một luật cho [dir="rtl"] đảo dấu quãng trượt. Luật này hoạt động khi thẻ html hoặc một thẻ cha có thuộc tính dir="rtl", cách phổ biến của các trang đa ngôn ngữ. Chữ ON/OFF cũng dùng thuộc tính logic nên đổi bên theo. Bật Xem hướng phải sang trái trong công cụ để kiểm tra.

Tương phản và chế độ tương phản cao

Tiêu chí 1.4.11 của WCAG yêu cầu các phần giao diện cần thiết để nhận ra trạng thái có tương phản tối thiểu 3:1 với màu liền kề. Với công tắc, đó là núm so với rãnh để thấy núm đang ở bên nào, và rãnh so với nền trang để thấy ranh giới công tắc. Công cụ đo các cặp này và báo khi thấp hơn 3:1, cùng với chữ ON/OFF so với rãnh theo ngưỡng 4,5:1. Ví dụ với mẫu iOS mặc định trên nền trắng, rãnh tắt #6b7280 đạt khoảng 4,83:1 và rãnh bật #15803d đạt khoảng 5,02:1. Ngoài ra, khi người dùng Windows bật chế độ tương phản cao, màu nền do trang đặt có thể bị thay thế và công tắc biến mất. Khối @media (forced-colors: active) trong mã chuyển công tắc sang màu hệ thống Canvas, CanvasText, Highlight để vẫn nhìn thấy.

Chuyển động và người dùng nhạy cảm

Núm trượt trong khoảng 200 ms là chuyển động nhỏ, nhưng kiểu nảy nhẹ cuối hành trình có đoạn vượt quá điểm đích rồi quay về. Mã luôn có khối prefers-reduced-motion tắt transition cho rãnh và núm, người dùng bật giảm chuyển động trong hệ điều hành sẽ thấy công tắc đổi trạng thái tức thì. Kiểu nảy dùng cubic-bezier(0.34, 1.56, 0.64, 1); nếu muốn tự chỉnh đường cong, bạn có thể thay giá trị này trong CSS.

Giới hạn cần biết

Công cụ tạo một kiểu công tắc hai trạng thái, không có trạng thái thứ ba như chưa xác định. Chữ ON/OFF chỉ để nhìn, dài quá khoảng trống trên rãnh sẽ bị núm che, nên giữ chữ ngắn và tăng chiều rộng khi cần. Luật RTL dựa vào thuộc tính dir trên thẻ cha, trang đổi hướng viết chỉ bằng CSS direction sẽ cần tự thêm luật tương ứng. Kết quả đo tương phản là gợi ý dựa trên công thức, không thay thế kiểm thử với người dùng thật. Công cụ không tạo biểu tượng bên trong núm như mặt trời, mặt trăng cho nút chế độ tối.

Câu hỏi thường gặp (FAQ)

Toggle switch CSS là gì?

Là công tắc bật/tắt được tạo kiểu bằng CSS, thường gồm một rãnh bo tròn và một núm trượt qua lại. Cách làm chuẩn là dựa trên một checkbox thật và chỉ dùng CSS để vẽ lại giao diện.

Vì sao không dùng thẻ div cho nhanh?

Thẻ div không nhận focus, không phản hồi phím Space, không có trạng thái cho trình đọc màn hình và không gửi được trong form. Muốn có đủ những thứ đó bạn phải tự viết thêm tabindex, role, aria-checked và xử lý bàn phím, trong khi checkbox đã có sẵn.

Có dùng button aria-pressed thay cho checkbox được không?

Được, đó là cách khác cho nút bật tắt, hợp với nút trên thanh công cụ như In đậm. Nhưng button không tự gửi giá trị trong form và bạn phải tự viết JavaScript đổi aria-pressed. Với thiết lập bật tắt trong form, checkbox có role="switch" gọn hơn.

Làm sao biết công tắc đang bật hay tắt bằng JavaScript?

Đọc thuộc tính checked của input: document.querySelector(".switch__input").checked trả về true khi bật. Lắng nghe sự kiện change để biết khi người dùng đổi trạng thái.

Vì sao nhấn Enter không bật được công tắc?

Vì công tắc là checkbox, và checkbox trong HTML chỉ đổi trạng thái bằng phím Space. Đây là hành vi chuẩn mà người dùng bàn phím đã quen, không phải lỗi.

Công tắc có hoạt động khi JavaScript bị tắt không?

Có. Việc bật tắt và đổi giao diện hoàn toàn do HTML và CSS đảm nhiệm. JavaScript chỉ cần khi bạn muốn làm gì đó ngay lúc trạng thái thay đổi.

Đặt công tắc bật sẵn thế nào?

Thêm thuộc tính checked vào thẻ input trong HTML, hoặc đặt input.checked = true bằng JavaScript.

Làm công tắc bị vô hiệu thế nào?

Thêm thuộc tính disabled vào input. CSS của công cụ làm rãnh mờ đi và đổi con trỏ thành biểu tượng cấm khi rê lên công tắc.

Vì sao công tắc biến mất trong chế độ tương phản cao?

Chế độ tương phản cao của Windows thay màu nền do trang đặt bằng màu hệ thống, nên rãnh và núm có thể cùng màu với nền. Khối forced-colors trong mã của công cụ đặt lại màu bằng các từ khóa màu hệ thống để công tắc vẫn hiện rõ.

Dùng trong React thế nào?

Giữ nguyên cấu trúc, đổi class thành className, dùng checked và onChange để điều khiển trạng thái. Không cần thư viện giao diện riêng.

Chữ ON/OFF có được trình đọc màn hình đọc không?

Không, vì rãnh chứa chữ có aria-hidden="true". Trạng thái được đọc từ role="switch", nên người dùng trình đọc màn hình không nghe lặp hai lần.

Làm công tắc to hơn cho điện thoại được không?

Được, tăng chiều rộng và chiều cao trong công cụ. Vì cả nhãn nằm trong label, vùng bấm thực tế đã rộng hơn nhiều so với riêng công tắc.

Công cụ có gửi dữ liệu đi đâu không?

Không. Việc sinh mã và xem thử diễn ra trong trình duyệt của bạn.

Từ khóa liên quan

  • toggle switch css
  • css toggle switch
  • công tắc bật tắt css
  • switch button css
  • toggle button html css
  • role switch
  • checkbox toggle css
  • ios toggle css
  • accessible toggle switch
  • toggle switch generator
  • nút gạt css
  • dark mode toggle css
  • toggle switch rtl
  • forced-colors css
  • focus-visible checkbox
  • custom checkbox css
  • toggle switch react
  • đọc trạng thái checkbox javascript
  • aria-pressed

Công cụ Design Tools liên quan

Dịch vụ của Tấn Phát Digital

Thiết kế xong rồi cần người biến nó thành sản phẩm chạy được trên web:

Dịch vụ thiết kế website tại Hồ Chí Minh

Website doanh nghiệp, bán hàng và đặt lịch, chuẩn SEO ngay từ cấu trúc, tốc độ tải dưới 3 giây.

Từ 5.000.000đXem chi tiết →

Dịch vụ thiết kế landing page

Trang đích riêng cho từng chiến dịch quảng cáo, tỷ lệ chuyển đổi 3–8%, bàn giao trong 5–21 ngày.

Từ 3.000.000đXem chi tiết →

Dịch vụ chăm sóc website định kỳ

Viết content SEO, tối ưu thứ hạng và A/B test chuyển đổi hàng tháng, cam kết KPI theo hợp đồng.

Từ 2.000.000đ/thángXem chi tiết →

Dịch vụ content social media

20–40 bài đăng và reels mỗi tháng cho Facebook, Instagram, TikTok, kèm quản lý cộng đồng.

Từ 5.000.000đ/thángXem chi tiết →

Tư vấn và báo giá miễn phí trong 24 giờ. Xem toàn bộ dịch vụ

Zalo
Facebook
TAN PHAT DIGITAL
Zalo
Facebook