Dark Mode Toggle với HTML, CSS và JavaScript — 5 mẫu từ cơ bản đến nâng cao

Dark mode không còn là “nice-to-have” — nó là yêu cầu cơ bản của mọi giao diện hiện đại. Tin vui là: chỉ với CSS variables và một chút JavaScript, bạn có thể xây dựng dark mode toggle mượt mà, nhẹ và dễ mở rộng. Bài này đi thẳng vào thực chiến với 5 mẫu khác nhau, từ cơ bản đến nâng cao. Demo chạy được ngay trong bài viết!

Dark Mode Toggle với HTML, CSS và JavaScript — 5 mẫu từ cơ bản đến nâng cao

Ý tưởng cốt lõi

Mọi cách làm dark mode đều dựa trên 3 cột trụ:

  • CSS Variables: Định nghĩa màu sắc cho light mode, ghi đè cho dark mode.
  • Class / Attribute toggle: JavaScript thêm/xóa class dark hoặc attribute data-theme.
  • Persistence: Lưu preference vào localStorage hoặc đọc từ prefers-color-scheme.

Mẫu 1: Toggle cơ bản với CSS Variables

Cách đơn giản nhất: dùng một class .dark trên container và định nghĩa màu tối bên trong. Phù hợp cho demo nhanh, prototype, hoặc component nhỏ.

HTML & CSS

<div class="dmt-box" id="demo1">
  <h3>🌞 Light Mode</h3>
  <button class="dmt-btn" onclick="toggle1()">Toggle</button>
</div>

<style>
  .dmt-box { background:#fff; color:#333; padding:30px; transition:all 0.3s; }
  .dmt-box.dark { background:#1a1a2e; color:#eee; }
  .dmt-btn { padding:10px 24px; border:none; border-radius:30px; cursor:pointer; background:#333; color:#fff; }
  .dmt-box.dark .dmt-btn { background:#f1c40f; color:#333; }
</style>

JavaScript

function toggle1() {
  document.getElementById('demo1').classList.toggle('dark');
}

Demo

Live Demo

🌞 Light Mode

Click nút bên dưới để chuyển đổi.

Mẫu 2: Toggle + localStorage (Nhớ preference)

Mẫu 1 mất trạng thái khi reload. Mẫu này lưu lựa chọn vào localStorage, đảm bảo user quay lại vẫn thấy đúng theme họ chọn. UI dùng switch toggle thay vì button — trực quan hơn.

HTML & CSS

<div class="dmt2-box" id="demo2">
  <h3>💾 Có nhớ preference</h3>
  <div class="dmt2-switch" onclick="toggle2()"></div>
</div>

<style>
  .dmt2-box { background:#f0f4f8; color:#2d3748; padding:30px; transition:all 0.4s; }
  .dmt2-box.night { background:#2d3748; color:#f0f4f8; }
  .dmt2-switch { width:60px; height:30px; background:#cbd5e0; border-radius:15px; position:relative; cursor:pointer; display:inline-block; transition:background 0.3s; }
  .dmt2-switch::after { content:''; width:26px; height:26px; background:#fff; border-radius:50%; position:absolute; top:2px; left:2px; transition:transform 0.3s; box-shadow:0 2px 4px rgba(0,0,0,0.2); }
  .dmt2-box.night .dmt2-switch { background:#4a5568; }
  .dmt2-box.night .dmt2-switch::after { transform:translateX(30px); background:#f6e05e; }
</style>

JavaScript

const dmt2Key = 'dmt-demo2-theme';

function toggle2() {
  const box = document.getElementById('demo2');
  const isDark = box.classList.toggle('night');
  localStorage.setItem(dmt2Key, isDark ? 'dark' : 'light');
}

(function() {
  const saved = localStorage.getItem(dmt2Key);
  if (saved === 'dark') document.getElementById('demo2').classList.add('night');
})();

Demo

Live Demo

💾 Có nhớ preference

Reload trang — theme vẫn giữ nguyên!

Mẫu 3: Tự động theo System Preference

Thay vì đoán user thích gì, hãy hỏi hệ điều hành. Dùng matchMedia('(prefers-color-scheme: dark)') để tự động bật dark mode nếu user đã để system ở chế độ tối. Kết hợp với change event để lắng nghe real-time.

HTML & CSS

<div class="dmt3-box" id="demo3">
  <h3>🖥️ Theo System</h3>
  <span id="dmt3-status">Đang lắng nghe...</span>
</div>

<style>
  .dmt3-box { background:#fff5f5; color:#742a2a; border:2px dashed #fc8181; padding:30px; transition:all 0.4s; }
  .dmt3-box.system-dark { background:#1a202c; color:#90cdf4; border-color:#4299e1; }
</style>

JavaScript

const mq = window.matchMedia('(prefers-color-scheme: dark)');
const demo3 = document.getElementById('demo3');
const status = document.getElementById('dmt3-status');

function apply(e) {
  if (e.matches) {
    demo3.classList.add('system-dark');
    status.textContent = 'System đang ở Dark Mode 🌙';
  } else {
    demo3.classList.remove('system-dark');
    status.textContent = 'System đang ở Light Mode ☀️';
  }
}
apply(mq);
mq.addEventListener('change', apply);

Demo

Live Demo

🖥️ Theo System

Tự động đổi khi bạn đổi theme Windows/macOS!

Đang lắng nghe…

Mẫu 4: Toggle với Animation “Chuyển cảnh” đẹp

Dark mode không chỉ là đổi màu — hãy kể một câu chuyện. Mẫu này dùng gradient chuyển động, hiệu ứng mặt trăng xuất hiện, và sao lấp lánh khi chuyển sang dark mode. Transition dùng cubic-bezier để tạo cảm giác “mượt”.

HTML & CSS

<div class="dmt4-scene" id="demo4">
  <div class="dmt4-moon"></div>
  <div class="dmt4-stars"></div>
  <h3>✨ Chuyển cảnh đẹp</h3>
  <button onclick="toggle4()">Chuyển đổi</button>
</div>

<style>
  .dmt4-scene { background:linear-gradient(135deg,#667eea,#764ba2); color:#fff; padding:40px; border-radius:12px; position:relative; overflow:hidden; transition:all 0.6s cubic-bezier(0.4,0,0.2,1); text-align:center; }
  .dmt4-scene.dark-mode { background:linear-gradient(135deg,#0f2027,#203a43,#2c5364); }
  .dmt4-moon { position:absolute; top:20px; right:30px; width:40px; height:40px; background:#f6e05e; border-radius:50%; box-shadow:0 0 20px #f6e05e; opacity:0; transform:translateY(20px); transition:all 0.6s ease; }
  .dmt4-scene.dark-mode .dmt4-moon { opacity:1; transform:translateY(0); }
  .dmt4-star { position:absolute; width:3px; height:3px; background:#fff; border-radius:50%; opacity:0; transition:opacity 0.6s; }
  .dmt4-scene.dark-mode .dmt4-star { opacity:0.8; animation:twinkle 2s infinite alternate; }
  @keyframes twinkle { 0%{opacity:0.3;transform:scale(0.8);} 100%{opacity:1;transform:scale(1.2);} }
</style>

JavaScript

function toggle4() {
  document.getElementById('demo4').classList.toggle('dark-mode');
}

(function() {
  const stars = document.querySelector('#demo4 .dmt4-stars');
  for (let i = 0; i < 20; i++) {
    const star = document.createElement('div');
    star.className = 'dmt4-star';
    star.style.left = Math.random() * 100 + '%';
    star.style.top = Math.random() * 100 + '%';
    star.style.animationDelay = Math.random() * 2 + 's';
    stars.appendChild(star);
  }
})();

Demo

Live Demo

✨ Chuyển cảnh đẹp

Gradient, mặt trăng, và sao lấp lánh.

Mẫu 5: 3 Chế độ — Light / Dark / Auto

Cách làm chuyên nghiệp nhất: cho user 3 lựa chọn. Light luôn sáng, Dark luôn tối, Auto theo system. Đây là pattern bạn thấy ở GitHub, YouTube, và hầu hết các app hiện đại.

HTML & CSS

<div class="dmt5-frame" id="demo5">
  <h3>🎛️ 3 Chế độ</h3>
  <div class="dmt5-selector">
    <button class="dmt5-opt active" onclick="set5('light')">☀️ Light</button>
    <button class="dmt5-opt" onclick="set5('dark')">🌙 Dark</button>
    <button class="dmt5-opt" onclick="set5('auto')">⚙️ Auto</button>
  </div>
</div>

<style>
  .dmt5-frame { background:#fff; color:#333; padding:30px; border-radius:8px; border:1px solid #e2e8f0; transition:all 0.4s; text-align:center; }
  .dmt5-frame.mode-dark { background:#1a202c; color:#e2e8f0; border-color:#2d3748; }
  .dmt5-frame.mode-auto { background:#edf2f7; color:#2d3748; border:2px solid #4299e1; }
  .dmt5-selector { display:inline-flex; gap:0; border-radius:8px; overflow:hidden; border:1px solid #cbd5e0; }
  .dmt5-opt { padding:10px 20px; border:none; background:#fff; cursor:pointer; font-weight:500; transition:all 0.2s; }
  .dmt5-opt.active { background:#4299e1; color:#fff; }
  .dmt5-frame.mode-dark .dmt5-opt { background:#2d3748; color:#e2e8f0; }
  .dmt5-frame.mode-dark .dmt5-opt.active { background:#63b3ed; color:#1a202c; }
  .dmt5-frame.mode-auto .dmt5-opt.active { background:#3182ce; color:#fff; }
</style>

JavaScript

const mq5 = window.matchMedia('(prefers-color-scheme: dark)');

function set5(mode, btn) {
  const frame = document.getElementById('demo5');
  const buttons = frame.querySelectorAll('.dmt5-opt');
  buttons.forEach(b => b.classList.remove('active'));
  btn.classList.add('active');
  frame.classList.remove('mode-dark','mode-auto');
  if (mode === 'dark') frame.classList.add('mode-dark');
  else if (mode === 'auto') {
    frame.classList.add('mode-auto');
    if (mq5.matches) frame.classList.add('mode-dark');
  }
}

mq5.addEventListener('change', (e) => {
  const frame = document.getElementById('demo5');
  if (frame.classList.contains('mode-auto')) {
    frame.classList.toggle('mode-dark', e.matches);
  }
});

Demo

Live Demo

🎛️ 3 Chế độ

Light, Dark, hoặc Auto theo system.



Bảng so sánh 5 mẫu

Mẫu Ưu điểm Nhược điểm Khi nào dùng
1. Cơ bản Code ngắn, dễ hiểu Mất trạng thái khi reload Demo, prototype nhanh
2. localStorage Nhớ preference user Không tự động theo system Web app, dashboard
3. System Zero-config cho user Không cho user override Blog, landing page đơn giản
4. Animation Trải nghiệm cao cấp CSS phức tạp hơn Portfolio, creative site
5. 3-Mode Linh hoạt nhất, chuẩn industry Logic phức tạp nhất SaaS, app production

Kết luận

Dark mode không cần thư viện nặng hay framework phức tạp. Với CSS variables, một chút JavaScript, và UIkit cho layout, bạn đã có đủ công cụ để triển khai từ prototype đến production.

Gợi ý tối ưu:

  • Đặt transition trên container để mọi element chuyển màu mượt mà.
  • Tránh flash white khi load bằng cách chạy JS đọc theme ngay trong <head> (inline script).
  • Dùng color-scheme: dark để browser tự đổi màu scrollbar, input, và các UI native.
  • Test kỹ contrast ratio — dark mode không chỉ là đảo màu đen trắng.

Copy code, dán vào project, chỉnh màu theo brand là chạy ngay. Chúc bạn toggle vui!

Bình luận


  • Không có bình luận.

Công cụ trực tuyến

Nhấn Ctrl + \ trên máy tính, hoặc vuốt sang trái ở bất kỳ đâu trên mobile.

Đăng nhập





Đang tải...