Cải thiện kiểu mặc định của chế độ tối bằng thuộc tính CSS phối màu và thẻ meta tương ứng

Thuộc tính CSS color-scheme và thẻ meta tương ứng cho phép nhà phát triển chọn sử dụng các trang của họ sử dụng chế độ mặc định dành riêng cho giao diện của biểu định kiểu tác nhân người dùng.

Thông tin khái quát

Tính năng đa phương tiện theo lựa chọn ưu tiên của người dùng prefers-color-scheme

Tính năng đa phương tiện theo lựa chọn ưu tiên của người dùng prefers-color-scheme cho phép nhà phát triển toàn quyền kiểm soát giao diện của trang. Nếu bạn chưa hiểu rõ về tính năng này, vui lòng đọc bài viết của tôi prefers-color-scheme: Xin chào bóng tối, người bạn cũ của tôi, trong đó tôi đã ghi lại mọi thứ mình biết về cách tạo ra những trải nghiệm tuyệt vời khi sử dụng chế độ tối.

Một mảnh ghép chỉ được đề cập ngắn gọn trong bài viết này là thuộc tính CSS color-scheme và thẻ meta tương ứng cùng tên. Cả hai đều giúp công việc phát triển của bạn trở nên dễ dàng hơn bằng cách cho phép bạn chọn sử dụng trang theo các chế độ mặc định dành riêng cho giao diện của biểu định kiểu tác nhân người dùng, chẳng hạn như tuỳ chọn điều khiển biểu mẫu, thanh cuộn cũng như màu hệ thống CSS. Đồng thời, tính năng này ngăn các trình duyệt tự áp dụng bất kỳ hành động biến đổi nào.

Hỗ trợ trình duyệt

prefers-color-scheme

Hỗ trợ trình duyệt

  • 76
  • 79
  • 67
  • 12.1

Nguồn

color-scheme

Hỗ trợ trình duyệt

  • 81
  • 81
  • 96
  • 13

Nguồn

Biểu định kiểu tác nhân người dùng

Trước khi tiếp tục, hãy để tôi mô tả ngắn gọn về biểu định kiểu tác nhân người dùng. Trong hầu hết trường hợp, bạn có thể nghĩ đến từ tác nhân người dùng (UA) theo cách thú vị hơn để nói trình duyệt. Biểu định kiểu UA xác định giao diện mặc định của trang. Như cái tên cho thấy, biểu định kiểu UA là thứ phụ thuộc vào UA được đề cập. Bạn có thể xem biểu định kiểu UA của Chrome (và Chromium) rồi so sánh với biểu định kiểu UA của Firefox hoặc Safari (và WebKit). Thông thường, biểu định kiểu UA thống nhất về hầu hết các nội dung. Ví dụ: tất cả các đường liên kết đều có màu xanh dương, văn bản chung có màu đen và màu nền trắng, nhưng cũng có những điểm khác biệt quan trọng (và đôi khi gây khó chịu), chẳng hạn như cách chúng tạo kiểu cho các chế độ điều khiển biểu mẫu.

Hãy xem xét kỹ hơn biểu định kiểu UA của WebKit và chức năng của biểu định kiểu này đối với chế độ tối. (Hãy tìm kiếm toàn bộ văn bản bằng từ "dark" trong biểu định kiểu.) Giá trị mặc định do biểu định kiểu cung cấp sẽ thay đổi tuỳ vào việc chế độ tối bật hay tắt. Để minh hoạ cho điều này, dưới đây là một quy tắc CSS như vậy bằng cách sử dụng lớp giả :matches và các biến WebKit-nội bộ như -apple-system-control-background, cũng như lệnh WebKit-internal bộ tiền xử lý #if defined:

input,
input:matches([type="password"], [type="search"]) {
  -webkit-appearance: textfield;
  #if defined(HAVE_OS_DARK_MODE_SUPPORT) &&
      HAVE_OS_DARK_MODE_SUPPORT
    color: text;
    background-color: -apple-system-control-background;
  #else
    background-color: white;
  #endif
  /* snip */
}

Bạn sẽ thấy một số giá trị không theo chuẩn cho các thuộc tính colorbackground-color ở trên. Cả text-apple-system-control-background đều không phải là màu CSS hợp lệ. Đó là các màu Semantic (ngữ nghĩa) nội bộ.

Hoá ra CSS có màu hệ thống ngữ nghĩa được chuẩn hoá. Các mô-đun này được quy định trong Mô-đun màu CSS cấp 4. Ví dụ: Canvas (đừng nhầm lẫn với thẻ <canvas>) là dành cho nền của nội dung hoặc tài liệu ứng dụng, trong khi CanvasText là dành cho văn bản trong nội dung hoặc tài liệu của ứng dụng. Cả hai kết hợp với nhau và không nên sử dụng riêng biệt.

Biểu định kiểu UA có thể sử dụng màu thuộc quyền sở hữu riêng hoặc màu của hệ thống ngữ nghĩa được chuẩn hoá để xác định cách hiển thị các phần tử HTML theo mặc định. Nếu bạn đặt hệ điều hành ở chế độ tối hoặc sử dụng giao diện tối, thì CanvasText (hoặc text) sẽ được đặt thành màu trắng theo điều kiện và Canvas (hoặc -apple-system-control-background) sẽ được đặt thành màu đen. Sau đó, biểu định kiểu UA sẽ chỉ định CSS sau đây một lần duy nhất, bao gồm cả chế độ sáng lẫn tối.

/**
  Not actual UA stylesheet code.
  For illustrative purposes only.
*/
body {
  color: CanvasText;
  background-color: Canvas
}

Thuộc tính CSS color-scheme

Quy cách Mô-đun điều chỉnh màu CSS cấp 1 giới thiệu một mô hình và các chức năng điều khiển tác nhân người dùng điều chỉnh màu tự động với mục tiêu xử lý các lựa chọn ưu tiên của người dùng, chẳng hạn như chế độ tối, điều chỉnh độ tương phản hoặc bảng phối màu cụ thể theo ý muốn.

Thuộc tính color-scheme được xác định trong đó cho phép một phần tử cho biết bảng phối màu phù hợp với chế độ kết xuất đó. Các giá trị này được thương lượng theo lựa chọn ưu tiên của người dùng, dẫn đến bảng phối màu được chọn sẽ ảnh hưởng đến những điều trên giao diện người dùng (UI), chẳng hạn như màu mặc định của các tuỳ chọn điều khiển biểu mẫu và thanh cuộn, cũng như giá trị đã sử dụng của màu hệ thống CSS. Các giá trị sau hiện đang được hỗ trợ:

  • normal Cho biết phần tử hoàn toàn không nhận biết bảng phối màu và vì vậy phần tử phải được kết xuất bằng bảng phối màu mặc định của trình duyệt.

  • [ light | dark ]+ Cho biết phần tử nhận biết và có thể xử lý các bảng phối màu được liệt kê, đồng thời thể hiện lựa chọn ưu tiên có thứ tự giữa các bảng phối màu đó.

Trong danh sách này, light đại diện cho bảng phối màu sáng, với màu nền sáng và màu nền trước tối, trong khi dark đại diện cho màu ngược lại, với màu nền tối và màu nền trước sáng.

Đối với tất cả các phần tử, việc hiển thị bằng bảng phối màu phải khiến màu sắc dùng trong tất cả giao diện người dùng do trình duyệt cung cấp cho phần tử đó khớp với ý định của bảng phối màu. Ví dụ: thanh cuộn, dấu gạch dưới kiểm tra lỗi chính tả, thanh điều khiển biểu mẫu, v.v.

Trên phần tử :root, việc hiển thị bằng bảng phối màu cũng phải ảnh hưởng đến màu bề mặt của canvas (tức là màu nền chung), giá trị ban đầu của thuộc tính color và giá trị đã sử dụng của màu hệ thống, đồng thời cũng ảnh hưởng đến thanh cuộn của khung nhìn.

/*
  The page supports both dark and light color schemes,
  and the page author prefers dark.
*/
:root {
  color-scheme: dark light;
}

Thẻ meta color-scheme

Việc tuân thủ thuộc tính CSS color-scheme yêu cầu CSS phải được tải xuống trước (nếu được tham chiếu qua <link rel="stylesheet">) và phải được phân tích cú pháp. Để hỗ trợ tác nhân người dùng hiển thị nền trang bằng bảng phối màu mong muốn ngay lập tức, bạn cũng có thể cung cấp giá trị color-scheme trong phần tử <meta name="color-scheme">.

<!--
  The page supports both dark and light color schemes,
  and the page author prefers dark.
-->
<meta name="color-scheme" content="dark light">

Kết hợp color-schemeprefers-color-scheme

Vì cả thẻ meta và thuộc tính CSS (nếu áp dụng cho phần tử :root) cuối cùng đều dẫn đến cùng một hành vi, nên bạn luôn nên chỉ định bảng phối màu thông qua thẻ meta để trình duyệt có thể áp dụng bảng phối màu ưu tiên nhanh hơn.

Mặc dù đối với các trang cơ sở tuyệt đối, bạn không cần có thêm quy tắc CSS nào, nhưng trong trường hợp chung, bạn nên luôn kết hợp color-scheme với prefers-color-scheme. Ví dụ: màu -webkit-link của CSS độc quyền, được WebKit và Chrome sử dụng cho màu xanh dương của đường liên kết cổ điển rgb(0,0,238), có tỷ lệ tương phản không đủ là 2,23:1 trên nền đen và không đạt cả WCAG AA cũng như yêu cầu của WCAG AAA.

Tôi đã mở các lỗi cho Chrome, WebKitFirefox cũng như một vấn đề meta trong Tiêu chuẩn HTML để khắc phục vấn đề này.

Tương tác với prefers-color-scheme

Lúc đầu, sự tương tác giữa thuộc tính CSS color-scheme và thẻ meta tương ứng với tính năng đa phương tiện theo lựa chọn ưu tiên của người dùng prefers-color-scheme có thể gây nhầm lẫn. Thực tế, hai người này phối hợp với nhau rất ăn ý. Điều quan trọng nhất cần hiểu là color-scheme xác định riêng giao diện mặc định, trong khi prefers-color-scheme xác định giao diện có thể tạo kiểu. Để làm cho vấn đề này rõ ràng hơn, hãy giả định trang sau:

<head>
  <meta name="color-scheme" content="dark light">
  <style>
    fieldset {
      background-color: gainsboro;
    }
    @media (prefers-color-scheme: dark) {
      fieldset {
        background-color: darkslategray;
      }
    }
  </style>
</head>
<body>
  <p>
    Lorem ipsum dolor sit amet, legere ancillae ne vis.
  </p>
  <form>
    <fieldset>
      <legend>Lorem ipsum</legend>
      <button type="button">Lorem ipsum</button>
    </fieldset>
  </form>
</body>

Mã CSS cùng dòng trên trang sẽ đặt background-color của phần tử <fieldset> thành gainsboro trong trường hợp chung và thành darkslategray nếu người dùng thích bảng phối màu dark theo tính năng đa phương tiện theo lựa chọn ưu tiên của người dùng prefers-color-scheme.

Thông qua phần tử <meta name="color-scheme" content="dark light">, trang cho trình duyệt biết rằng trang này hỗ trợ giao diện tối và sáng, trong đó ưu tiên giao diện tối.

Tuỳ thuộc vào việc hệ điều hành được đặt ở chế độ tối hay sáng, toàn bộ trang sẽ chuyển sang chế độ sáng khi tối hoặc ngược lại, dựa trên biểu định kiểu tác nhân người dùng. Không có CSS bổ sung nào do nhà phát triển cung cấp để thay đổi văn bản của đoạn văn bản hoặc màu nền của trang.

Hãy lưu ý cách background-color của phần tử <fieldset> thay đổi tuỳ vào việc chế độ tối có được bật hay không theo các quy tắc trong biểu định kiểu cùng dòng do nhà phát triển cung cấp trên trang. Đó là gainsboro hoặc darkslategray.

Một trang ở chế độ sáng.
Chế độ sáng: Các kiểu do nhà phát triển và tác nhân người dùng chỉ định. Theo biểu định kiểu tác nhân người dùng, văn bản có màu đen và nền màu trắng. background-color của phần tử <fieldset>gainsboro theo biểu định kiểu nhà phát triển cùng dòng.
Một trang ở chế độ tối.
Chế độ tối:Kiểu do nhà phát triển và tác nhân người dùng chỉ định. Văn bản có màu trắng và nền màu đen theo biểu định kiểu tác nhân người dùng. background-color của phần tử <fieldset>darkslategray theo biểu định kiểu nhà phát triển cùng dòng.

Giao diện của phần tử <button> do biểu định kiểu tác nhân người dùng kiểm soát. color của lớp này được đặt thành màu hệ thống ButtonText, background-color và bốn border-color được đặt thành màu hệ thống ButtonFace.

Trang chế độ sáng sử dụng thuộc tính ButtonFace.
Chế độ sáng: background-color và nhiều border-color được đặt thành màu hệ thống ButtonFace.

Bây giờ, hãy lưu ý cách border-color của phần tử <button> thay đổi. Giá trị đã tính cho border-top-colorborder-bottom-color chuyển từ rgba(0, 0, 0, 0.847) (màu đen) sang rgba(255, 255, 255, 0.847) (màu trắng), vì tác nhân người dùng cập nhật ButtonFace một cách linh động dựa trên bảng phối màu. Điều này cũng áp dụng cho color của phần tử <button> được đặt thành màu hệ thống ButtonText tương ứng.

Cho thấy các giá trị màu đã tính toán khớp với ButtonFace.
Chế độ sáng: Các giá trị đã tính toán của border-top-colorborder-bottom-color đều được đặt thành ButtonFace trong biểu định kiểu tác nhân người dùng giờ đây là rgba(0, 0, 0, 0.847).
Cho thấy các giá trị màu đã tính toán vẫn khớp với ButtonFace khi ở chế độ tối.
Chế độ tối: Các giá trị đã tính toán của border-top-colorborder-bottom-color đều được đặt thành ButtonFace trong biểu định kiểu tác nhân người dùng giờ đây là rgba(255, 255, 255, 0.847).

Bản minh hoạ

Bạn có thể thấy hiệu ứng của color-scheme được áp dụng cho nhiều phần tử HTML trong bản minh hoạ về Glitch. Bản minh hoạ cố ý cho thấy lỗi WCAG AA và WCAG AAA cùng với các màu liên kết được đề cập trong cảnh báo ở trên.

Bản minh hoạ khi ở chế độ sáng.
Bản minh hoạ được chuyển thành color-scheme: light.
Bản minh hoạ khi ở chế độ tối.
Bản minh hoạ được chuyển thành color-scheme: dark. Vui lòng lưu ý lỗi vi phạm WCAG AA và WCAG AAA kèm theo màu của đường liên kết.

Xác nhận

Rune Lillesveen đã triển khai thuộc tính CSS color-scheme và thẻ meta tương ứng. Rune cũng là người đồng chỉnh sửa thông số kỹ thuật Cấp 1 của Mô-đun điều chỉnh màu CSS. Hình ảnh chính của Philippe Leone trên Unsplash.