Preferreds-color-scheme: Xin chào bóng tối, bạn cũ của tôi

Đánh bóng hay cần thiết? Tìm hiểu mọi thứ về chế độ tối và cách hỗ trợ chế độ này để mang lại lợi ích cho người dùng!

Giới thiệu

Chế độ tối trước Chế độ tối

Màn hình máy tính có phông xanh lục
Màn hình xanh lục (Nguồn)

Chúng tôi đã hoàn tất việc triển khai chế độ tối. Vào thời kỳ đầu của máy tính cá nhân, chế độ tối không phải là lựa chọn mà là thực tế: Màn hình máy tính CRT đơn sắc hoạt động bằng cách bắn chùm electron vào màn hình huỳnh quang và chất huỳnh quang dùng trong các CRT đời đầu có màu xanh lục. Vì văn bản hiển thị bằng màu xanh lục và phần còn lại của màn hình có màu đen, nên các mô hình này thường được gọi là màn hình xanh lục.

Xử lý văn bản màu tối trên nền trắng
Tối trên nền trắng (Nguồn)

Màn hình CRT màu được giới thiệu sau đó hiển thị nhiều màu thông qua việc sử dụng chất phát quang màu đỏ, xanh lục và xanh dương. Họ tạo ra màu trắng bằng cách kích hoạt đồng thời cả ba chất phát quang. Với sự ra đời của công nghệ WYSIWYG (như bạn thấy, như vậy) xuất bản trên máy tính tinh vi hơn, ý tưởng tạo tài liệu ảo giống như một tờ giấy thực tế đã trở nên phổ biến.

Trang web màu tối trên nền trắng trong trình duyệt WorldWideWeb
Trình duyệt WorldWideWeb (Nguồn)

Đây là nơi bắt đầu xu hướng thiết kế màu tối trên nền trắng, và xu hướng này đã được chuyển sang web dựa trên tài liệu ban đầu. Trình duyệt đầu tiên, WorldWideWeb (hãy nhớ rằng CSS thậm chí còn chưa được phát minh), hiển thị trang web theo cách này. Thông tin thú vị: trình duyệt thứ hai, Line Mode Browser (Trình duyệt chế độ dòng) – một trình duyệt dựa trên thiết bị đầu cuối – có màu xanh lục trên nền tối. Ngày nay, các trang web và ứng dụng web thường được thiết kế với văn bản tối trên nền sáng, một giả định cơ sở cũng được mã hoá cứng trong các tệp kiểu của tác nhân người dùng, bao gồm cả Chrome.

Điện thoại thông minh được sử dụng khi nằm trên giường
Người dùng điện thoại thông minh trên giường (Nguồn: Unsplash)

Thời đại của màn hình CRT đã qua từ lâu. Hoạt động tiêu thụ và sáng tạo nội dung đã chuyển sang các thiết bị di động sử dụng màn hình LCD có đèn nền hoặc màn hình AMOLED tiết kiệm năng lượng. Máy tính, máy tính bảng và điện thoại thông minh nhỏ gọn và dễ di chuyển hơn đã dẫn đến các mẫu sử dụng mới. Các hoạt động giải trí như duyệt web, lập trình cho vui và chơi trò chơi cao cấp thường diễn ra sau giờ làm việc trong môi trường thiếu sáng. Mọi người thậm chí còn sử dụng thiết bị trên giường vào ban đêm. Càng có nhiều người sử dụng thiết bị trong bóng tối, ý tưởng quay lại với giao diện màu sáng trên nền tối càng trở nên phổ biến.

Lý do sử dụng chế độ tối

Chế độ tối vì lý do thẩm mỹ

Khi được hỏi vì sao họ thích hoặc muốn dùng chế độ tối, câu trả lời phổ biến nhất là "dễ nhìn hơn", theo sau là "đẹp và thanh lịch". Trong tài liệu dành cho nhà phát triển về Chế độ tối, Apple viết rõ: "Việc chọn bật giao diện sáng hay tối là một lựa chọn thẩm mỹ đối với hầu hết người dùng và có thể không liên quan đến điều kiện ánh sáng xung quanh".

CloseView trong Mac OS System 7 với
System 7 CloseView (Source)

Chế độ tối làm công cụ hỗ trợ tiếp cận

Cũng có những người thực sự cần chế độ tối và sử dụng chế độ này như một công cụ hỗ trợ tiếp cận khác, ví dụ: người dùng có thị lực kém. Lần xuất hiện sớm nhất của một công cụ hỗ trợ tiếp cận như vậy mà tôi có thể tìm thấy là tính năng CloseView của System 7. Tính năng này có nút bật/tắt cho chế độ Đen trên trắngTrắng trên đen. Mặc dù Hệ thống 7 hỗ trợ màu sắc, nhưng giao diện người dùng mặc định vẫn là màu đen trắng.

Các phương thức triển khai dựa trên phép đảo ngược này đã cho thấy điểm yếu của chúng sau khi màu sắc được đưa vào. Nghiên cứu của Szpiro và cộng sự về cách những người có thị lực kém truy cập vào thiết bị điện toán cho thấy rằng tất cả người dùng được phỏng vấn đều không thích hình ảnh đảo ngược, nhưng nhiều người lại thích văn bản sáng trên nền tối. Apple đáp ứng lựa chọn ưu tiên này của người dùng bằng một tính năng có tên là Đảo màu thông minh. Tính năng này đảo ngược màu sắc trên màn hình, ngoại trừ hình ảnh, nội dung nghe nhìn và một số ứng dụng sử dụng kiểu màu tối.

Một dạng đặc biệt của thị lực kém là Hội chứng thị giác máy tính, còn gọi là Hội chứng mỏi mắt kỹ thuật số. Hội chứng này được xác định"sự kết hợp của các vấn đề về mắt và thị lực liên quan đến việc sử dụng máy tính (bao gồm cả máy tính để bàn, máy tính xách tay và máy tính bảng) và các màn hình điện tử khác (ví dụ: điện thoại thông minh và thiết bị đọc điện tử)."đề xuất rằng việc thanh thiếu niên sử dụng thiết bị điện tử, đặc biệt là vào ban đêm, sẽ làm tăng nguy cơ thời lượng ngủ ngắn hơn, thời gian bắt đầu ngủ lâu hơn và thiếu ngủ nhiều hơn. Ngoài ra, theo nghiên cứu của Rosenfield, việc tiếp xúc với ánh sáng xanh được báo cáo rộng rãi là có liên quan đến việc điều chỉnh nhịp sinh học và chu kỳ ngủ, đồng thời môi trường ánh sáng không đều có thể dẫn đến tình trạng thiếu ngủ, có thể ảnh hưởng đến tâm trạng và hiệu suất thực hiện nhiệm vụ. Để hạn chế những tác động tiêu cực này, bạn có thể giảm ánh sáng xanh dương bằng cách điều chỉnh nhiệt độ màu màn hình thông qua các tính năng như Chế độ ban đêm của iOS hoặc Ánh sáng ban đêm của Android, cũng như tránh ánh sáng chói hoặc ánh sáng không đều nói chung thông qua giao diện tối hoặc chế độ tối.

Tiết kiệm pin ở chế độ tối trên màn hình AMOLED

Cuối cùng, chế độ tối được biết là tiết kiệm nhiều năng lượng trên màn hình AMOLED. Các nghiên cứu điển hình trên Android tập trung vào các ứng dụng phổ biến của Google như YouTube cho thấy mức tiết kiệm pin có thể lên đến 60%. Video bên dưới có thêm thông tin chi tiết về các nghiên cứu điển hình này và mức tiết kiệm pin trên mỗi ứng dụng.

Kích hoạt chế độ tối trong hệ điều hành

Giờ đây, tôi đã trình bày lý do chế độ tối lại quan trọng với nhiều người dùng, hãy cùng xem cách bạn có thể hỗ trợ chế độ này.

Chế độ cài đặt chế độ tối trên Android Q
Cài đặt giao diện tối trên Android Q

Các hệ điều hành hỗ trợ chế độ tối hoặc giao diện tối thường có tuỳ chọn để kích hoạt chế độ này ở một nơi nào đó trong phần cài đặt. Trên macOS X, phần này nằm trong mục General (Chung) của phần lựa chọn ưu tiên hệ thống và có tên là Appearance (Giao diện) (ảnh chụp màn hình). Còn trên Windows 10, phần này nằm trong mục Colors (Màu sắc) và có tên là Choose your color (Chọn màu) (ảnh chụp màn hình). Đối với Android Q, bạn có thể tìm thấy chế độ này trong phần Màn hình dưới dạng nút bật/tắt Giao diện tối (ảnh chụp màn hình), và trên iOS 13, bạn có thể thay đổi Giao diện trong phần Màn hình và độ sáng của phần cài đặt (ảnh chụp màn hình).

Truy vấn nội dung đa phương tiện prefers-color-scheme

Một chút lý thuyết cuối cùng trước khi tôi bắt đầu. Truy vấn nội dung nghe nhìn cho phép tác giả kiểm thử và truy vấn các giá trị hoặc tính năng của tác nhân người dùng hoặc thiết bị hiển thị, độc lập với tài liệu đang được hiển thị. Các hàm này được dùng trong quy tắc @media CSS để áp dụng kiểu theo điều kiện cho một tài liệu, cũng như trong nhiều ngữ cảnh và ngôn ngữ khác, chẳng hạn như HTML và JavaScript. Truy vấn nội dung nghe nhìn cấp 5 giới thiệu các tính năng nội dung nghe nhìn ưu tiên của người dùng, tức là một cách để các trang web phát hiện cách người dùng muốn hiển thị nội dung.

Tính năng nội dung nghe nhìn prefers-color-scheme được dùng để phát hiện xem người dùng có yêu cầu trang sử dụng giao diện màu sáng hay tối hay không. Phương thức này hoạt động với các giá trị sau:

  • light: Cho biết người dùng đã thông báo cho hệ thống rằng họ muốn một trang có giao diện sáng (văn bản tối trên nền sáng).
  • dark: Cho biết người dùng đã thông báo cho hệ thống rằng họ muốn một trang có giao diện tối (văn bản sáng trên nền tối).

Hỗ trợ chế độ tối

Tìm hiểu xem trình duyệt có hỗ trợ chế độ tối hay không

Vì chế độ tối được báo cáo thông qua truy vấn nội dung đa phương tiện, nên bạn có thể dễ dàng kiểm tra xem trình duyệt hiện tại có hỗ trợ chế độ tối hay không bằng cách kiểm tra xem truy vấn nội dung đa phương tiện prefers-color-scheme có khớp hay không. Lưu ý cách tôi không đưa bất kỳ giá trị nào vào, mà chỉ kiểm tra xem truy vấn nội dung nghe nhìn có khớp hay không.

if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') {
  console.log('🎉 Dark mode is supported');
}

Tại thời điểm viết bài, prefers-color-scheme được hỗ trợ trên cả máy tính và thiết bị di động (nếu có) bởi Chrome và Edge kể từ phiên bản 76, Firefox kể từ phiên bản 67, và Safari kể từ phiên bản 12.1 trên macOS và kể từ phiên bản 13 trên iOS. Đối với tất cả trình duyệt khác, bạn có thể xem phần Tôi có thể sử dụng bảng hỗ trợ không.

Tìm hiểu về lựa chọn ưu tiên của người dùng tại thời điểm yêu cầu

Tiêu đề gợi ý ứng dụng Sec-CH-Prefers-Color-Scheme cho phép các trang web lấy lựa chọn ưu tiên về bảng phối màu của người dùng (không bắt buộc) tại thời điểm yêu cầu, cho phép máy chủ nội tuyến CSS phù hợp và do đó tránh hiện tượng nhấp nháy giao diện màu không chính xác.

Áp dụng chế độ tối

Cuối cùng, hãy xem cách hỗ trợ chế độ tối trong thực tế. Giống như Highlander, với chế độ tối chỉ có thể có một chế độ: tối hoặc sáng, nhưng không bao giờ có cả hai! Tại sao tôi đề cập đến điều này? Vì thực tế này sẽ tác động đến chiến lược tải. Vui lòng không buộc người dùng tải CSS xuống trong đường dẫn kết xuất quan trọng dành cho một chế độ mà họ hiện không sử dụng. Do đó, để tối ưu hoá tốc độ tải, tôi đã chia CSS cho ứng dụng mẫu cho thấy các đề xuất sau đây trong thực tế thành ba phần để hoãn CSS không quan trọng:

  • style.css chứa các quy tắc chung được sử dụng phổ biến trên trang web.
  • dark.css chỉ chứa các quy tắc cần thiết cho chế độ tối.
  • light.css chỉ chứa các quy tắc cần thiết cho chế độ sáng.

Chiến lược tải

Hai phần tử sau, light.cssdark.css, được tải có điều kiện bằng truy vấn <link media>. Ban đầu, không phải trình duyệt nào cũng hỗ trợ prefers-color-scheme (có thể phát hiện bằng mẫu ở trên). Tôi xử lý vấn đề này một cách linh động bằng cách tải tệp light.css mặc định thông qua phần tử <link rel="stylesheet"> được chèn có điều kiện trong một tập lệnh nội tuyến nhỏ (màu sáng là một lựa chọn tuỳ ý, tôi cũng có thể đặt màu tối làm trải nghiệm dự phòng mặc định). Để tránh nội dung không được định kiểu, tôi ẩn nội dung của trang cho đến khi light.css tải xong.

<script>
  // If `prefers-color-scheme` is not supported, fall back to light mode.
  // In this case, light.css will be downloaded with `highest` priority.
  if (window.matchMedia('(prefers-color-scheme: dark)').media === 'not all') {
    document.documentElement.style.display = 'none';
    document.head.insertAdjacentHTML(
      'beforeend',
      '<link rel="stylesheet" href="/light.css" onload="document.documentElement.style.display = \'\'">',
    );
  }
</script>
<!--
  Conditionally either load the light or the dark stylesheet. The matching file
  will be downloaded with `highest`, the non-matching file with `lowest`
  priority. If the browser doesn't support `prefers-color-scheme`, the media
  query is unknown and the files are downloaded with `lowest` priority (but
  above I already force `highest` priority for my default light experience).
-->
<link rel="stylesheet" href="/dark.css" media="(prefers-color-scheme: dark)" />
<link
  rel="stylesheet"
  href="/light.css"
  media="(prefers-color-scheme: light)"
/>
<!-- The main stylesheet -->
<link rel="stylesheet" href="/style.css" />

Cấu trúc của tệp định kiểu

Tôi tận dụng tối đa các biến CSS, điều này cho phép style.css chung của tôi trở thành chung, và tất cả các tuỳ chỉnh chế độ sáng hoặc tối đều diễn ra trong hai tệp khác là dark.csslight.css. Dưới đây là một đoạn trích về các kiểu thực tế, nhưng đoạn trích này là đủ để truyền tải ý tưởng tổng thể. Tôi khai báo hai biến, -⁠-⁠color-⁠-⁠background-color, về cơ bản tạo ra giao diện cơ sở tối trên sángsáng trên tối.

/* light.css: 👉 dark-on-light */
:root {
  --color: rgb(5, 5, 5);
  --background-color: rgb(250, 250, 250);
}
/* dark.css: 👉 light-on-dark */
:root {
  --color: rgb(250, 250, 250);
  --background-color: rgb(5, 5, 5);
}

Trong style.css, tôi sử dụng các biến này trong quy tắc body { … }. Vì các lớp này được xác định trên lớp giả lập CSS :root – một bộ chọn trong HTML đại diện cho phần tử <html> và giống với bộ chọn html, ngoại trừ việc mức độ cụ thể của lớp này cao hơn – các lớp này sẽ xếp chồng xuống, giúp tôi khai báo các biến CSS chung.

/* style.css */
:root {
  color-scheme: light dark;
}

body {
  color: var(--color);
  background-color: var(--background-color);
}

Trong mã mẫu ở trên, có thể bạn đã nhận thấy một thuộc tính color-scheme có giá trị light dark được phân tách bằng dấu cách.

Điều này cho trình duyệt biết ứng dụng của tôi hỗ trợ giao diện màu nào và cho phép trình duyệt kích hoạt các biến thể đặc biệt của tệp kiểu của tác nhân người dùng. Điều này rất hữu ích, ví dụ: cho phép trình duyệt hiển thị các trường biểu mẫu có nền tối và văn bản sáng, điều chỉnh thanh cuộn hoặc bật màu nổi bật nhận biết giao diện. Thông tin chi tiết chính xác về color-scheme được chỉ định trong Mô-đun điều chỉnh màu CSS cấp 1.

Sau đó, mọi thứ khác chỉ là vấn đề xác định các biến CSS cho những điều quan trọng trên trang web của tôi. Việc sắp xếp các kiểu theo ngữ nghĩa sẽ giúp ích rất nhiều khi làm việc với chế độ tối. Ví dụ: thay vì -⁠-⁠highlight-yellow, hãy cân nhắc gọi biến -⁠-⁠accent-color, vì "yellow" (vàng) có thể không thực sự có màu vàng ở chế độ tối hoặc ngược lại. Dưới đây là ví dụ về một số biến khác mà tôi sử dụng trong ví dụ của mình.

/* dark.css */
:root {
  --color: rgb(250, 250, 250);
  --background-color: rgb(5, 5, 5);
  --link-color: rgb(0, 188, 212);
  --main-headline-color: rgb(233, 30, 99);
  --accent-background-color: rgb(0, 188, 212);
  --accent-color: rgb(5, 5, 5);
}
/* light.css */
:root {
  --color: rgb(5, 5, 5);
  --background-color: rgb(250, 250, 250);
  --link-color: rgb(0, 0, 238);
  --main-headline-color: rgb(0, 0, 192);
  --accent-background-color: rgb(0, 0, 238);
  --accent-color: rgb(250, 250, 250);
}

Ví dụ đầy đủ

Trong phần nhúng Glitch sau đây, bạn có thể xem ví dụ hoàn chỉnh về cách áp dụng các khái niệm ở trên vào thực tế. Hãy thử bật/tắt chế độ tối trong chế độ cài đặt của hệ điều hành cụ thể và xem trang phản ứng như thế nào.

Tác động khi tải

Khi chơi với ví dụ này, bạn có thể thấy lý do tôi tải dark.csslight.css thông qua truy vấn nội dung đa phương tiện. Hãy thử bật/tắt chế độ tối và tải lại trang: các tệp kiểu hiện không khớp vẫn được tải, nhưng có mức độ ưu tiên thấp nhất để không bao giờ cạnh tranh với các tài nguyên mà trang web cần ngay lúc này.

Sơ đồ tải mạng cho thấy cách CSS của chế độ tối được tải ở chế độ sáng với mức độ ưu tiên thấp nhất
Trang web ở chế độ sáng sẽ tải CSS chế độ tối với mức độ ưu tiên thấp nhất.
Sơ đồ tải mạng cho thấy cách CSS ở chế độ sáng được tải ở mức độ ưu tiên thấp nhất ở chế độ tối
Trang web ở chế độ tối sẽ tải CSS ở chế độ sáng với mức độ ưu tiên thấp nhất.
Sơ đồ tải mạng cho thấy cách CSS của chế độ tối được tải ở mức độ ưu tiên thấp nhất trong chế độ sáng mặc định
Trang web ở chế độ sáng mặc định trên trình duyệt không hỗ trợ prefers-color-scheme sẽ tải CSS chế độ tối ở mức độ ưu tiên thấp nhất.

Phản ứng với các thay đổi về chế độ tối

Giống như mọi thay đổi khác đối với truy vấn nội dung nghe nhìn, bạn có thể đăng ký nhận các thay đổi đối với chế độ tối thông qua JavaScript. Ví dụ: bạn có thể sử dụng tính năng này để linh động thay đổi favicon của một trang hoặc thay đổi <meta name="theme-color"> giúp xác định màu của thanh URL trong Chrome. Ví dụ đầy đủ ở trên cho thấy cách thực hiện việc này. Để xem các thay đổi về màu giao diện và biểu tượng trang web, hãy mở bản minh hoạ trong một thẻ riêng.

const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
darkModeMediaQuery.addEventListener('change', (e) => {
  const darkModeOn = e.matches;
  console.log(`Dark mode is ${darkModeOn ? '🌒 on' : '☀️ off'}.`);
});

Kể từ Chromium 93 và Safari 15, bạn có thể điều chỉnh màu sắc dựa trên truy vấn nội dung nghe nhìn bằng thuộc tính media của phần tử màu giao diện meta. Hệ thống sẽ chọn tên đầu tiên khớp với tên bạn nhập. Ví dụ: bạn có thể có một màu cho chế độ sáng và một màu khác cho chế độ tối. Tại thời điểm viết bài, bạn không thể xác định những giá trị đó trong tệp kê khai. Xem vấn đề GitHub w3c/manifest#975.

<meta
  name="theme-color"
  media="(prefers-color-scheme: light)"
  content="white"
/>
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black" />

Gỡ lỗi và kiểm thử chế độ tối

Mô phỏng prefers-color-scheme trong Công cụ cho nhà phát triển

Việc chuyển đổi bảng phối màu của toàn bộ hệ điều hành có thể gây khó chịu rất nhanh, vì vậy, Chrome DevTools hiện cho phép bạn mô phỏng bảng phối màu mà người dùng ưu tiên theo cách chỉ ảnh hưởng đến thẻ hiện đang hiển thị. Mở Command Menu (Trình đơn lệnh), bắt đầu nhập Rendering, chạy lệnh Show Rendering, sau đó thay đổi tuỳ chọn Emulate CSS media feature prefers-color-scheme (Mô phỏng tính năng đa phương tiện CSS prefers-color-scheme).

Ảnh chụp màn hình của tuỳ chọn &quot;Emulate CSS media feature prefers-color-scheme&quot; (Mô phỏng tính năng đa phương tiện CSS prefers-color-scheme) nằm trong thẻ Kết xuất của Chrome DevTools

Chụp ảnh màn hình prefers-color-scheme bằng Puppeteer

Puppeteer là một thư viện Node.js cung cấp API cấp cao để kiểm soát Chrome hoặc Chromium thông qua Giao thức DevTools. Với dark-mode-screenshot, chúng tôi cung cấp một tập lệnh Puppeteer cho phép bạn tạo ảnh chụp màn hình của các trang ở cả chế độ tối và sáng. Bạn có thể chạy tập lệnh này một lần hoặc đưa tập lệnh này vào bộ kiểm thử Tích hợp liên tục (CI).

npx dark-mode-screenshot --url https://googlechromelabs.github.io/dark-mode-toggle/demo/ --output screenshot --fullPage --pause 750

Các phương pháp hay nhất về chế độ tối

Tránh màu trắng tinh

Một chi tiết nhỏ mà bạn có thể nhận thấy là tôi không sử dụng màu trắng tinh khiết. Thay vào đó, để ngăn hiện tượng phát sáng và tràn màu trên nội dung tối xung quanh, tôi chọn màu trắng hơi đậm hơn. Bạn có thể sử dụng rgb(250, 250, 250).

Tô màu lại và làm tối hình ảnh chụp

Nếu so sánh hai ảnh chụp màn hình dưới đây, bạn sẽ nhận thấy rằng không chỉ giao diện cốt lõi đã thay đổi từ tối trên sáng thành sáng trên tối, mà hình ảnh chính cũng có chút khác biệt. Nghiên cứu người dùng của tôi cho thấy rằng phần lớn những người được khảo sát thích hình ảnh ít rực rỡ và sống động hơn một chút khi chế độ tối đang hoạt động. Tôi gọi đây là tái tô màu.

Hình ảnh chính hơi tối hơn ở chế độ tối.
Hình ảnh chính hơi tối ở chế độ tối.
Hình ảnh chính thông thường ở chế độ sáng.
Hình ảnh chính thông thường ở chế độ sáng.

Tôi có thể tô màu lại thông qua bộ lọc CSS trên hình ảnh. Tôi sử dụng bộ chọn CSS khớp với tất cả hình ảnh không có .svg trong URL, ý tưởng là tôi có thể xử lý lại màu sắc của đồ hoạ vectơ (biểu tượng) khác với hình ảnh (ảnh) của tôi, hãy xem thêm về điều này trong đoạn tiếp theo. Lưu ý cách tôi sử dụng lại biến CSS để sau này có thể linh hoạt thay đổi bộ lọc.

Vì chỉ cần tô màu lại ở chế độ tối, tức là khi dark.css đang hoạt động, nên không có quy tắc tương ứng nào trong light.css.

/* dark.css */
--image-filter: grayscale(50%);

img:not([src*='.svg']) {
  filter: var(--image-filter);
}

Tuỳ chỉnh cường độ tô màu lại của chế độ tối bằng JavaScript

Mọi người đều khác nhau và có nhu cầu khác nhau về chế độ tối. Bằng cách tuân thủ phương thức tô màu lại được mô tả ở trên, tôi có thể dễ dàng đặt cường độ thang màu xám làm lựa chọn ưu tiên của người dùng mà tôi có thể thay đổi thông qua JavaScript. Ngoài ra, bằng cách đặt giá trị 0%, tôi cũng có thể tắt hoàn toàn tính năng tô màu lại. Xin lưu ý rằng document.documentElement cung cấp thông tin tham chiếu đến phần tử gốc của tài liệu, tức là cùng một phần tử mà tôi có thể tham chiếu bằng lớp giả CSS :root.

const filter = 'grayscale(70%)';
document.documentElement.style.setProperty('--image-filter', value);

Đảo ngược đồ hoạ vectơ và biểu tượng

Đối với đồ hoạ vectơ (trong trường hợp của tôi, được dùng làm biểu tượng mà tôi tham chiếu thông qua các phần tử <img>), tôi sử dụng một phương thức tô màu lại khác. Mặc dù nghiên cứu cho thấy rằng mọi người không thích chế độ đảo ngược cho ảnh, nhưng chế độ này hoạt động rất hiệu quả đối với hầu hết các biểu tượng. Một lần nữa, tôi sử dụng các biến CSS để xác định lượng đảo ngược trong trạng thái thông thường và trạng thái :hover.

Biểu tượng được đảo ngược ở chế độ tối.
Các biểu tượng được đảo ngược ở chế độ tối.
Biểu tượng thông thường ở chế độ sáng.
Biểu tượng thông thường ở chế độ sáng.

Xin lưu ý rằng tôi chỉ đảo ngược các biểu tượng trong dark.css chứ không phải trong light.css, cũng như cách :hover nhận được cường độ đảo ngược khác nhau trong hai trường hợp để biểu tượng xuất hiện hơi tối hơn hoặc sáng hơn một chút, tuỳ thuộc vào chế độ mà người dùng đã chọn.

/* dark.css */
--icon-filter: invert(100%);
--icon-filter_hover: invert(40%);

img[src*='.svg'] {
  filter: var(--icon-filter);
}
/* light.css */
--icon-filter_hover: invert(60%);
/* style.css */
img[src*='.svg']:hover {
  filter: var(--icon-filter_hover);
}

Sử dụng currentColor cho SVG cùng dòng

Đối với hình ảnh SVG cùng dòng, thay vì sử dụng bộ lọc đảo ngược, bạn có thể tận dụng từ khoá CSS currentColor đại diện cho giá trị của thuộc tính color của một phần tử. Điều này cho phép bạn sử dụng giá trị color trên các thuộc tính không nhận được giá trị đó theo mặc định. Để thuận tiện, nếu currentColor được dùng làm giá trị của thuộc tính fill hoặc stroke của SVG, thì giá trị của thuộc tính này sẽ được lấy từ giá trị kế thừa của thuộc tính màu. Tuyệt vời hơn nữa: cách này cũng hoạt động với <svg><use href="…"></svg>, vì vậy, bạn có thể có các tài nguyên riêng biệt và currentColor vẫn sẽ được áp dụng theo ngữ cảnh. Xin lưu ý rằng cách này chỉ hoạt động với SVG nội tuyến hoặc <use href="…">, nhưng không hoạt động với SVG được tham chiếu dưới dạng src của hình ảnh hoặc theo cách nào đó thông qua CSS. Bạn có thể xem cách áp dụng trong bản minh hoạ bên dưới.

<!-- Some inline SVG -->
<svg xmlns="http://www.w3.org/2000/svg"
    stroke="currentColor"
>
  […]
</svg>

Chuyển đổi mượt mà giữa các chế độ

Bạn có thể chuyển đổi từ chế độ tối sang chế độ sáng hoặc ngược lại một cách mượt mà nhờ cả colorbackground-color đều là các thuộc tính CSS có thể tạo ảnh động. Bạn có thể dễ dàng tạo ảnh động bằng cách khai báo hai transition cho hai thuộc tính. Ví dụ dưới đây minh hoạ ý tưởng tổng thể, bạn có thể trải nghiệm trực tiếp trong bản minh hoạ.

body {
  --duration: 0.5s;
  --timing: ease;

  color: var(--color);
  background-color: var(--background-color);

  transition: color var(--duration) var(--timing), background-color var(
        --duration
      ) var(--timing);
}

Hướng dẫn nghệ thuật với chế độ tối

Mặc dù về lý do hiệu suất tải nói chung, bạn nên làm việc riêng với prefers-color-scheme trong thuộc tính media của phần tử <link> (thay vì cùng dòng trong các tệp định kiểu), nhưng có những trường hợp bạn thực sự muốn làm việc với prefers-color-scheme ngay trong mã HTML. Chỉ đạo nghệ thuật là một tình huống như vậy. Trên web, định hướng nghệ thuật liên quan đến giao diện tổng thể của trang và cách giao diện đó truyền đạt thông tin trực quan, kích thích tâm trạng, tương phản các tính năng và thu hút đối tượng mục tiêu về mặt tâm lý.

Với chế độ tối, nhà thiết kế có thể quyết định hình ảnh nào là tốt nhất ở một chế độ cụ thể và liệu việc tô màu lại hình ảnhkhông đủ tốt hay không. Nếu được sử dụng với phần tử <picture>, <source> của hình ảnh sẽ hiển thị có thể phụ thuộc vào thuộc tính media. Trong ví dụ bên dưới, tôi hiển thị bán cầu Tây cho chế độ tối và bán cầu Đông cho chế độ sáng hoặc khi không có lựa chọn ưu tiên nào, mặc định là bán cầu Đông trong mọi trường hợp khác. Tất nhiên, đây chỉ là ví dụ minh hoạ. Bật/tắt chế độ tối trên thiết bị để thấy sự khác biệt.

<picture>
  <source srcset="western.webp" media="(prefers-color-scheme: dark)" />
  <source srcset="eastern.webp" media="(prefers-color-scheme: light)" />
  <img src="eastern.webp" />
</picture>

Chế độ tối, nhưng thêm lựa chọn không sử dụng

Như đã đề cập trong phần lý do nên dùng chế độ tối ở trên, chế độ tối là lựa chọn thẩm mỹ cho hầu hết người dùng. Do đó, một số người dùng có thể thực sự muốn giao diện người dùng của hệ điều hành ở chế độ tối, nhưng vẫn muốn xem trang web theo cách họ quen nhìn. Một mẫu tuyệt vời là ban đầu tuân thủ tín hiệu mà trình duyệt gửi qua prefers-color-scheme, nhưng sau đó cho phép người dùng ghi đè chế độ cài đặt cấp hệ thống của họ (không bắt buộc).

Phần tử tuỳ chỉnh <dark-mode-toggle>

Tất nhiên, bạn có thể tự tạo mã cho việc này, nhưng bạn cũng có thể chỉ cần sử dụng một phần tử tuỳ chỉnh tạo sẵn (thành phần web) mà tôi đã tạo ngay cho mục đích này. Tệp này có tên là <dark-mode-toggle> và sẽ thêm một nút bật/tắt (chế độ tối: bật/tắt) hoặc trình chuyển đổi giao diện (giao diện: sáng/tối) vào trang mà bạn có thể tuỳ chỉnh toàn bộ. Bản minh hoạ bên dưới cho thấy phần tử đang hoạt động (và tôi cũng 🤫 âm thầm đưa phần tử này vào tất cả các ví dụ khác ở trên).

<dark-mode-toggle
  legend="Theme Switcher"
  appearance="switch"
  dark="Dark"
  light="Light"
  remember="Remember this"
></dark-mode-toggle>
nút chuyển chế độ tối ở chế độ sáng.
<dark-mode-toggle> ở chế độ sáng.
nút chuyển chế độ tối ở chế độ sáng.
<dark-mode-toggle> ở chế độ tối.

Hãy thử nhấp hoặc nhấn vào các nút điều khiển chế độ tối ở góc trên bên phải trong bản minh hoạ bên dưới. Nếu bạn đánh dấu vào hộp đánh dấu trong chế độ điều khiển thứ ba và thứ tư, hãy xem cách lựa chọn chế độ của bạn được ghi nhớ ngay cả khi bạn tải lại trang. Điều này cho phép khách truy cập giữ hệ điều hành của họ ở chế độ tối, nhưng vẫn thưởng thức trang web của bạn ở chế độ sáng hoặc ngược lại.

Kết luận

Việc làm việc và hỗ trợ chế độ tối rất thú vị và mở ra nhiều hướng thiết kế mới. Đối với một số khách truy cập, điều này có thể là sự khác biệt giữa việc không thể xử lý trang web của bạn và việc trở thành một người dùng hài lòng. Có một số cạm bẫy và bạn chắc chắn phải kiểm thử cẩn thận, nhưng chế độ tối chắc chắn là một cơ hội tuyệt vời để bạn thể hiện rằng bạn quan tâm đến tất cả người dùng. Các phương pháp hay nhất được đề cập trong bài đăng này và các trình trợ giúp như phần tử tuỳ chỉnh <dark-mode-toggle> sẽ giúp bạn tự tin tạo ra trải nghiệm chế độ tối tuyệt vời. Hãy cho tôi biết trên Twitter về nội dung bạn tạo và liệu bài đăng này có hữu ích hay không, cũng như đề xuất để cải thiện bài đăng này. Cảm ơn bạn đã đọc! 🌒

Tài nguyên cho truy vấn nội dung nghe nhìn prefers-color-scheme:

Tài nguyên về thẻ meta color-scheme và thuộc tính CSS:

Các đường liên kết chung về chế độ tối:

Các bài viết nghiên cứu cơ bản cho bài đăng này:

Lời cảm ơn

Tính năng đa phương tiện prefers-color-scheme, thuộc tính CSS color-scheme và thẻ meta liên quan là công việc triển khai của 👏 Rune Lillesveen. Rune cũng là đồng biên tập của thông số kỹ thuật Mô-đun điều chỉnh màu CSS cấp 1. Tôi xin 🙏 cảm ơn Lukasz Zbylut, Rowan Merewood, Chirag Desai, và Rob Dodson vì đã xem xét kỹ lưỡng bài viết này. Chiến lược tải là ý tưởng của Jake Archibald. Emilio Cobos Álvarez đã chỉ cho tôi phương pháp phát hiện prefers-color-scheme chính xác. Mẹo về SVG và currentColor được tham chiếu đến là của Timothy Hatcher. Cuối cùng, tôi muốn cảm ơn nhiều người tham gia ẩn danh trong nhiều nghiên cứu về người dùng đã giúp định hình các đề xuất trong bài viết này. Hình ảnh chính của Nathan Anderson.