3 cách xây dựng dark mode cho website

Dark mode đang là xu thế của các website hiện nay. Dark mode giúp người đọc đỡ mỏi mắt khi nhìn vào màn hình trong thời gian dài, đặc biệt là vào buổi tối.

Để xây dựng một giao diện có thể chuyển đổi qua lại giữa dark mode và light mode thật sự không quá khó. Bài viết này mình sẽ trình bày 3 cách đơn giản để xây dựng dark mode cho website nhé.

Let’s get started !

toggle dark mode

Chuẩn bị một giao diện

Đầu tiên chúng ta cần chuẩn bị một giao diện ở chế độ light mode nhé. Giao diện sẽ trông như thế này.

Giao diện chế độ sáng
Giao diện chế độ sáng
<body>
  <!-- box content -->
  <div class="wrapper">
    <div class="box">
      <h1 class="title">Toggle Dark Mode</h1>
      <p class="text">
        Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolor tenetur maiores
        delectus odio quianesciunt obcaecati explicabo repellendus similique neque.
      </p>
    </div>
  </div>

  <!-- theme toggle button -->
  <div id="toggleBtn"></div>
</body>
body {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  background-color: #f5f5f5;

  display: flex;
  align-items: center;
  justify-content: center;
}

.title {
  font-size: 24px;
  color: #1e1e1e;
}

.text {
  font-size: 16px;
  color: #4e4e4e;
}

.wrapper {
  width: 500px;
  text-align: center;
  padding: 48px;
  box-shadow: rgba(100, 100, 110, 0.2) 0px 8px 28px 0px;
  background-color: #fff;
  border-radius: 12px;
}

#toggleBtn {
  width: 80px;
  height: 40px;
  border-radius: 20px;
  background-color: #888;
  box-shadow: rgba(100, 100, 110, 0.2) 0px 8px 28px 0px;

  position: fixed;
  left: 50px;
  bottom: 50px;
}

#toggleBtn::before {
  content: '';
  position: absolute;
  left: 2px;
  bottom: 2px;

  width: 36px;
  height: 36px;
  background-color: #fff;
  border-radius: 50%;

  cursor: pointer;
  transition: all 0.35s;
}

#toggleBtn.active::before {
  transform: translateX(40px);
}

Cách 1: Sử dụng biến trong CSS (CSS Variable)

Đây là cách dễ nhất, mình hay sử dụng nhất và cũng dễ tuỳ biến nhất. Với cách này chúng ta có thể làm ra nhiều theme khác nhau thay vì chỉ có light mode và dark mode.

Ưu điểm: Rất dễ tuỳ chỉnh theo ý muốn, dễ quản lý, code đồng nhất.

Khuyết điểm: mình chưa nghĩ ra 🤣

Bước 1: Thêm một thuộc tính data-theme="light" vào thẻ html dùng để toggle qua lại giữa dark mode và light mode (bạn có thể đặt tên thuộc tính khác nhé).

<html lang="en" data-theme="light">

Bước 2: Sử dụng CSS Variable để tạo một bảng màu (color palette) mặc định dành cho light mode:

:root {
  --bg-color-primary: #f5f5f5;
  --bg-color-secondary: #fff;
  --bg-toggle-btn: #888;
  --box-shadow: rgba(100, 100, 110, 0.2) 0px 8px 28px 0px;
  --title-color: #1e1e1e;
  --text-color: #4e4e4e;
}

Bước 3: Thay tất cả CSS nào dùng màu đã được set cứng thành các biến thông qua từ khoá var():

body {
  /* ... */
  background-color: var(--bg-color-primary);
}

.title {
  /* ... */
  color: var(--title-color);
}

.text {
  /* ... */
  color: var(--text-color);
}

.wrapper {
  /* ... */
  box-shadow: var(--box-shadow);
  background-color: var(--bg-color-secondary);
}

#toggleBtn {
  /* ... */
  background-color: var(--bg-toggle-btn);
  box-shadow: var(--box-shadow);
}

#toggleBtn::before {
  /* ... */
  background-color: var(--bg-color-secondary);
}

Bước 4: Tạo một bảng màu cho dark mode. Bạn chỉ cần thay đổi giá trị của các biến đã tạo ở bước 2. Lưu ý: thuộc tính [data-theme="dark"] phải khớp với thuộc tính ở bước 1.

[data-theme='dark'] {
  --bg-color-primary: #18191a;
  --bg-color-secondary: #242526;
  --bg-toggle-btn: #4e4f50;
  --box-shadow: rgba(25, 25, 25, 0.2) 0px 8px 28px 0px;
  --title-color: #f1f2f3;
  --text-color: #d4d5d6;
}

Bước 5: Dùng JavaScript để toggle 2 chế độ là xong 😉

window.onload = function () {
	const themeBtn = document.getElementById('toggleBtn');

	themeBtn.addEventListener('click', function () {
		// Lấy thuộc tính data-theme
		const root = document.querySelector(':root');
		const isLightMode =
			root.getAttribute('data-theme') === 'dark' ? false : true;

		// toggle theme mode
		if (isLightMode) {
			root.setAttribute('data-theme', 'dark');
		} else {
			root.setAttribute('data-theme', 'light');
		}

		// thay đổi vị trí của button
		this.classList.toggle('active');
	});
};

Và đây là thành quả:

Result toggle dark mode

Cách 2: Style với class như bình thường

Cách này cũng khá dễ dàng và quen thuộc, chúng ta chỉ cần thêm một class để toggle vào thẻ body, sau đó dựa vào sự xuất hiện của class đó mà thay đổi màu sắc.

Ưu điểm: Thông dụng, dễ tiếp cận.

Nhược điểm: Code khó đồng nhất, viết css dài dòng.

Bước 1: Chọn 1 class để làm cờ báo hiệu dark mode, ở đây mình dùng darkmode-active. Viết CSS cho các thẻ cần đổi màu khi qua dark mode:

body.darkmode-active {
  background-color: #18191a;
}

.darkmode-active .wrapper {
  box-shadow: rgba(25, 25, 25, 0.2) 0px 8px 28px 0px;
  background-color: #242526;
}

.darkmode-active .title {
  color: #f1f2f3;
}

.darkmode-active .text {
  color: #d4d5d6;
}

.darkmode-active #toggleBtn {
  background-color: #4e4f50;
  box-shadow: rgba(25, 25, 25, 0.2) 0px 8px 28px 0px;
}

.darkmode-active #toggleBtn::before {
  background-color: #242526;
}

Bước 2: Dùng JavaScript để toggle 2 chế độ là xong 😎

window.onload = function () {
	const themeBtn = document.getElementById('toggleBtn');

	themeBtn.addEventListener('click', function () {
		document.body.classList.toggle('darkmode-active');

		this.classList.toggle('active');
	});
};

Cách 3: Dùng các file CSS riêng biệt

Cách này là cách dark nhất nhưng vẫn sử dụng được 😂 Chúng ta chỉ cần tách biệt các đoạn code CSS liên quan đến màu sắc ra các file css riêng biệt như light-mode.css, dark-mode.css, pink-mode.css. Sau đó, dùng JS để thay đổi href của thẻ link.

Ưu điểm: Các file css gọn gàng, tường minh hơn.

Nhược điểm: Code bị phân mảnh nhiều hơn, quản lý nhiều file css hơn, khó tuỳ biến hơn.

Bước 1: Tách các code css nào có liên quan đến màu sắc mà bạn cần đổi ra file css riêng, ở đây file mình là light-mode.css. Sau đó, nhúng nó vào file HTML của bạn.

body {
  background-color: #f5f5f5;
}

.wrapper {
  box-shadow: rgba(100, 100, 110, 0.2) 0px 8px 28px 0px;
  background-color: #fff;
}

.title {
  color: #1e1e1e;
}

.text {
  color: #4e4e4e;
}

#toggleBtn {
  background-color: #888;
  box-shadow: rgba(100, 100, 110, 0.2) 0px 8px 28px 0px;
}

#toggleBtn::before {
  background-color: #fff;
}

Bước 2: Đặt một id="themeCssLink" vào thẻ link mà bạn nhúng file css đó vào.

<link rel="stylesheet" href="./light-mode.css" id="themeCssLink">

Bước 3: Tạo một file dark-mode.css và thay đổi màu sắc giao diện theo ý của bạn.

body {
  background-color: #18191a;
}

.wrapper {
  box-shadow: rgba(25, 25, 25, 0.2) 0px 8px 28px 0px;
  background-color: #242526;
}

.title {
  color: #f1f2f3;
}

.text {
  color: #d4d5d6;
}

#toggleBtn {
  background-color: #4e4f50;
  box-shadow: rgba(25, 25, 25, 0.2) 0px 8px 28px 0px;
}

#toggleBtn::before {
  background-color: #242526;
}

Bước 4: Viết JS để toggle chế độ là xong 😉

window.onload = function () {
	const themeBtn = document.getElementById('toggleBtn');

	themeBtn.addEventListener('click', function () {
		const linkTag = document.getElementById('themeCssLink');

		if (linkTag) {
			const href = linkTag.getAttribute('href');
			// kiểm tra đường dẫn có phải là file chứa light mode css không?
			const isLightMode = href?.indexOf('light-mode') !== -1;

			if (isLightMode) {
				linkTag.setAttribute('href', './dark-mode.css');
			} else {
				linkTag.setAttribute('href', './light-mode.css');
			}
		}

		this.classList.toggle('active');
	});
};

Lưu lại trạng thái dark mode của người dùng

Có một vấn đề mà chúng ta chưa xử lý đó là khi người dùng reload lại trang thì chế độ mà họ đang dùng hiện tại cũng sẽ biến mất và trở về mặc định là light mode.

Cách dễ nhất để giải quyết là chúng ta sẽ lưu trạng thái này vào localStorage. Và mỗi lần khi người dùng vào website chúng ta sẽ tải lại trạng thái đó.

function setTheme(isLight = true) {
	const theme = isLight ? 'light' : 'dark';
	localStorage.setItem('theme', theme);
}
function loadTheme() {
	// Lấy giá trị của theme đã được lưu trong localStorage
	// Nếu không có thì mặc định là 'light'
	const theme = localStorage.getItem('theme') || 'light';

	// Thay đổi vị trí của nút toggle nếu là dark mode
	if (theme !== 'light') {
		document.getElementById('toggleBtn').classList.add('active');
	}

	// Chọn 1 trong 3 cách load bên dưới phù hợp với cách bạn dùng
	// load cho cách 1: dùng css variable
	document.querySelector(':root').setAttribute('data-theme', theme);

	// load cho cách 2: dùng css style
	if (theme !== 'light') {
		document.body.classList.add('darkmode-active');
	}

	// load cho cách 3: dùng file css riêng biệt
	if (theme !== 'light') {
		document
			.getElementById('themeCssLink')
			?.setAttribute('href', './dark-mode.css');
	}
}

Tóm tắt

Mọi người có thể xem và tải full source code ở đây nhé: Github

Yeah, rất đơn giản đúng không nào, bên trên là tất tần tật những gì mình biết để xây dựng một giao diện dark mode. Còn nhiều cách khác để triển khai, nếu bạn biết cách nào nữa thì để lại bình luận cho mình biết với nhé.

Mong rằng bài viết này bổ ích với mọi người. Cảm ơn mọi người đã đọc bài viết này ❤

Bạn có thể đọc thêm:

6 Comments

  1. datt8386 10/06/2022
  2. Đinh Gia Huy 31/08/2021
  3. Trần Vinh 29/08/2021
  4. Along 29/08/2021
  5. Trần Đăng Khoa 09/08/2021

Give a Comment