Thêm chế độ tối (dark mode) cho website bằng biến CSS và một chút JavaScript

  • author-image

    Nguyễn Đình Cường

  • blog-tag
  • blog-comment 0 comment
  • created-date 09 Nov, 2026
blog-thumbnail

Chế độ tối giờ gần như là tính năng mặc định mà người dùng mong đợi: dễ chịu khi dùng ban đêm và tiết kiệm pin trên một số màn hình. Bài này hướng dẫn bạn thêm dark mode cho website bằng biến CSS, tôn trọng thiết lập hệ thống và cho phép người dùng tự chọn.

Chiến lược ba lớp

Một dark mode tử tế xử lý ba tình huống:

  1. Mặc định theo thiết lập hệ điều hành của người dùng (sáng hoặc tối).
  2. Cho phép người dùng ghi đè bằng nút bật tắt.
  3. Nhớ lựa chọn ở lần truy cập sau.

Nền tảng của cách làm là biến CSS (custom properties): ta định nghĩa các màu một lần dưới dạng biến, mọi thành phần dùng biến đó, rồi chế độ tối chỉ cần đổi giá trị của biến.

Bước 1: Định nghĩa biến màu

:root {
  --bg: #ffffff;
  --surface: #f3f4f6;
  --text: #111827;
  --muted: #6b7280;
  --border: #e5e7eb;
  --accent: #4f46e5;
}

/* Tối theo hệ thống, trừ khi người dùng đã chọn sáng */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0b1220;
    --surface: #111a2e;
    --text: #e5e7eb;
    --muted: #9ca3af;
    --border: #243049;
    --accent: #818cf8;
  }
}

/* Tối khi người dùng chọn thủ công */
:root[data-theme="dark"] {
  --bg: #0b1220;
  --surface: #111a2e;
  --text: #e5e7eb;
  --muted: #9ca3af;
  --border: #243049;
  --accent: #818cf8;
}

Truy vấn prefers-color-scheme đọc thiết lập sáng/tối của hệ thống. Bộ chọn :root:not([data-theme="light"]) nghĩa là: nếu hệ thống chọn tối và người dùng không ép sáng thì dùng màu tối. Thuộc tính data-theme trên thẻ html là công tắc mà JavaScript sẽ điều khiển.

Bước 2: Dùng biến trong style

body {
  background: var(--bg);
  color: var(--text);
  transition: background-color .2s, color .2s;
}
.card {
  background: var(--surface);
  border: 1px solid var(--border);
}
a { color: var(--accent); }
small, .muted { color: var(--muted); }

Hãy tránh viết cứng màu như #fff hay black ở khắp nơi, nếu không sẽ có những mảng vẫn sáng khi bật chế độ tối. Thêm dòng <meta name="color-scheme" content="light dark"> trong head để trình duyệt cũng tô thanh cuộn và các ô nhập mặc định đúng tông.

Bước 3: Nút bật tắt

<button id="theme-toggle" aria-label="Chuyển chế độ sáng tối">Giao diện</button>
(function () {
  var root = document.documentElement;
  var KEY = 'theme';

  function systemPrefersDark() {
    return window.matchMedia('(prefers-color-scheme: dark)').matches;
  }

  function currentTheme() {
    var saved = null;
    try { saved = localStorage.getItem(KEY); } catch (e) {}
    if (saved === 'light' || saved === 'dark') return saved;
    return systemPrefersDark() ? 'dark' : 'light';
  }

  function applyTheme(theme) {
    root.setAttribute('data-theme', theme);
  }

  applyTheme(currentTheme());

  document.getElementById('theme-toggle').addEventListener('click', function () {
    var next = root.getAttribute('data-theme') === 'dark' ? 'light' : 'dark';
    applyTheme(next);
    try { localStorage.setItem(KEY, next); } catch (e) {}
  });
})();

Khối try/catch quanh localStorage cần thiết vì trong chế độ riêng tư hoặc khi bị chặn lưu trữ, truy cập có thể ném lỗi. Trang vẫn hoạt động, chỉ không nhớ lựa chọn.

Tránh hiện tượng nháy trắng

Nếu script nằm cuối trang, trình duyệt có thể vẽ nền sáng một thoáng rồi mới chuyển tối. Cách khắc phục: đặt một đoạn script nhỏ ngay trong head, trước khi trang được vẽ, chỉ làm việc đọc lựa chọn và gán data-theme. Phần xử lý nút bấm có thể để cuối trang.

Kiểm tra chất lượng

  • Độ tương phản chữ và nền đủ rõ ở cả hai chế độ.
  • Màu nhấn trên nền tối thường cần sáng hơn một chút so với nền sáng.
  • Hình ảnh và biểu tượng nền trắng có thể chói trên nền tối; cân nhắc dùng ảnh trong suốt hoặc lọc độ sáng.
  • Tránh dùng đen tuyền hoàn toàn cho nền và trắng tinh cho chữ, hai màu hơi dịu một chút dễ đọc hơn.
  • Thử bằng công cụ giả lập của DevTools: mục Rendering cho phép đổi prefers-color-scheme.

Kết luận

Biến CSS biến việc đổi giao diện thành việc đổi vài giá trị. Kết hợp thiết lập hệ thống, nút chọn thủ công và ghi nhớ, bạn có một dark mode gọn, đáng tin và tôn trọng người dùng. Cùng kỹ thuật này có thể mở rộng thành nhiều bộ giao diện khác.

Nếu muốn học CSS và thiết kế giao diện một cách bài bản, hãy tham khảo các khóa học tại codebem.com.

author_photo
Nguyễn Đình Cường

0 comment