- Tóm lược 8 cấp độ phân chia giúp mở rộng dần phạm vi triển khai chế độ tối, từ tính năng mặc định của trình duyệt đến media query trong JavaScript
- Cách đơn giản nhất là chỉ cần khai báo
<meta name="color-scheme" content="light dark"> hoặc color-scheme: light dark để đi theo tùy chọn bảng màu của người dùng
- Ở các cấp cao hơn, có thể điều chỉnh rộng rãi không chỉ màu sắc mà cả hình ảnh và đổ bóng bằng hàm
light-dark(), @media (prefers-color-scheme: dark), và stylesheet tách riêng theo scheme
- Có thể xây dựng bộ chuyển đổi với 3 lựa chọn Automatic·light·dark thay vì chỉ bám theo thiết lập hệ thống của người dùng, đồng thời dùng
:has() và phần tử meta thực tế để nhận diện theme
- Bài viết cũng đề cập giới hạn về khả năng tiếp cận của Safari và quan sát về cách
prefers-color-scheme hoạt động khi in, cho thấy gần đây việc tích hợp sẵn chế độ sáng/tối bằng CSS đã trở nên dễ dàng hơn nhiều
Triển khai chế độ tối theo từng cấp độ
-
Level 1: Barebone
- Có thể bật phân biệt light/dark mà không cần một dòng CSS nào; chỉ cần thêm
<meta name="color-scheme" content="light dark"> vào phần head của tài liệu là trình duyệt sẽ bắt đầu tuân theo tùy chọn bảng màu của người dùng
- Về mặt lý thuyết, thứ tự các mục trong thuộc tính
content có ý nghĩa; người dùng không chỉ định tùy chọn bảng màu sẽ nhận giá trị đầu tiên trong danh sách phân tách bằng dấu cách
- Hiện tại không có tùy chọn “không chọn bảng màu” trong thiết lập hệ điều hành, nên trên thực tế kết quả sẽ quy về scheme trùng với thiết lập hệ điều hành
- Cũng có thể chỉ định một giá trị duy nhất trong
content; khi đó scheme đó sẽ được áp dụng cưỡng chế mà không xét đến tùy chọn của người dùng
- Thẻ meta này phần nào đóng vai trò là cách làm phía HTML tương ứng với phương thức CSS ở cấp tiếp theo
-
Level 2: Basic
- Trong CSS, có thể áp dụng phân biệt chế độ sáng/tối bằng khai báo
html { color-scheme: light dark; }
- Nếu trong DOM đã có thẻ meta thì không cần khai báo này; nếu có thể kiểm soát HTML, nên dùng thẻ meta vì trình duyệt có thể biết chỉ dẫn đó từ trước khi parse CSS
- Cả hai cách đều cho phép tận dụng style mặc định của user agent cùng với chế độ sáng/tối có sẵn trong đó
- Nếu bổ sung thêm CSS nhưng chủ yếu giới hạn ở việc dùng CSS system colors, vẫn có thể tạo ra một thiết kế khá gọn gàng
- Khác với thẻ meta luôn áp dụng cho toàn bộ tài liệu, khai báo CSS
color-scheme còn có thể đặt ở các vị trí khác ngoài phần tử gốc, tạo thêm không gian ứng dụng
-
Level 3: Benign
- Có thể tinh chỉnh chế độ sáng/tối đơn giản bằng hàm màu
light-dark() của CSS, được bổ sung tương đối gần đây
- Trong ví dụ, hàm được dùng như
background-color: light-dark(black, white); và color: light-dark(white, black);; đối số thứ nhất áp dụng cho chế độ sáng và đối số thứ hai áp dụng cho chế độ tối
- Đối số có thể là màu trực tiếp hoặc custom properties được diễn giải thành màu
- Trong toàn bộ bài viết, tại thời điểm được viết chỉ riêng cấp này là chưa có hỗ trợ trình duyệt đủ tốt
-
Level 4: Bold
- Có thể triển khai chuyển đổi chế độ tối bằng media query truyền thống
@media (prefers-color-scheme: dark)
- Dù truy vấn
light hay dark, cách này vẫn cho phép mức độ tùy biến tối đa, không bị giới hạn ở việc đổi màu đơn giản
- Có thể thực hiện mọi kiểu điều chỉnh như làm ảnh bớt rực bằng filter trong chế độ tối, hoặc thay box shadow bằng đường viền
-
Level 5: Bisectional
- Media query cũng có thể dùng trong HTML; có thể đặt vào thuộc tính
media của phần tử link để tách stylesheet theo từng scheme
- Ví dụ được đưa ra là nối
light.css và dark.css lần lượt với prefers-color-scheme: light và prefers-color-scheme: dark
- Khi phạm vi tùy biến lớn, cấu hình bằng các file chuyên dụng là phù hợp; trình duyệt cũng có thể bỏ qua file CSS không khớp truy vấn, nhờ đó có thể giảm bớt một file cần tải xuống
-
Level 6: Ballistic
- Trong JavaScript, có thể dùng media query cho bảng màu qua
window.matchMedia('(prefers-color-scheme:dark)')
- Tương tự các media query khác, có thể truy vấn xem scheme hiện tại là sáng hay tối rồi thực hiện xử lý mong muốn dựa trên kết quả đó
- Trong triển khai thực tế, không nhất thiết phải bám vào duy nhất một kỹ thuật ở các cấp trước mà có thể kết hợp nhiều cách
Bộ chuyển đổi người dùng và các mẫu nâng cao
-
Level 7: Beyond
- Không nhất thiết phải chỉ dựa vào tùy chọn hệ thống của người dùng; có thể xây dựng bộ chuyển đổi color scheme
- Bộ chuyển đổi này không phải boolean đơn giản; cần có chế độ Automatic làm giá trị mặc định ban đầu để đi theo
prefers-color-scheme
- Khi thêm bộ chuyển đổi vào, người dùng sẽ có thể chọn một trong ba chế độ: Automatic, light, dark
-
Level 8: Beguiling
- Khi triển khai bộ chuyển đổi ở Level 7, cách phổ biến thường là thêm class
.dark hoặc thuộc tính như data-theme="dark" vào phần tử HTML
- Nhưng thay vào đó có thể dùng
:has() để truy vấn trực tiếp sự tồn tại của <meta name="color-scheme" content="dark">
- Trong ví dụ, dưới selector
html:has(meta[name="color-scheme"][content="dark"]), các biến CSS như --color-bg, --color-text được đặt thành giá trị cho chế độ tối
- Nhờ vậy có thể nhận diện theme dựa trên phần tử meta thực tế mà không cần class hay thuộc tính dữ liệu riêng
Thảo luận và quan sát bổ sung
-
Quan sát từ CSS Naked Day
- Sau khi bỏ style, gần như mọi trang được ghé thăm đều cho thấy rõ sự thiếu vắng chế độ tối, và điều đó dẫn tới việc phân chia các cấp độ của chế độ tối
- Tác giả cũng nhắc rằng khi xây một trang mới từ đầu và viết style mới, các tính năng CSS gần đây khiến việc tích hợp sẵn chế độ sáng/tối trở nên rất dễ dàng
-
Vấn đề khả năng tiếp cận của Safari
- Bài viết chỉ ra rằng cho tới tương đối gần đây, Safari vẫn không cung cấp màu liên kết có khả năng tiếp cận trong chế độ tối
- Trong một CSS Naked Day trước đó, tác giả đã phát hiện vấn đề này và gỡ thẻ meta để chỉ dùng bảng màu sáng
- Sau đó thẻ meta đã được thêm lại, nhưng tác giả nhận thức rằng với người dùng Safari phiên bản cũ, điều này có thể làm giảm khả năng tiếp cận
- Cũng xác nhận rằng trong chế độ tối của Safari, hộp văn bản không có đường viền nhìn thấy được
- Chỉ dựa vào style mặc định của user agent thì ngay cả khi dùng HTML ngữ nghĩa đúng cũng không thể bảo đảm khả năng tiếp cận hoàn chỉnh; vì vậy tác giả đang cân nhắc giữ lại đủ style trong các kỳ CSS Naked Day tới
-
In ấn và điều kiện screen and
- Trong ví dụ Bisectional, việc dùng
screen and ... được giải thích là để loại trừ thiết bị in
- Tác giả giả định có một stylesheet lõi không phụ thuộc theme hoặc stylesheet in riêng, và cho rằng việc tách an toàn như vậy là hợp lý vì chế độ tối khi in có thể tốn nhiều mực
- Trong thử nghiệm thực tế, ngay cả khi bật chế độ tối ở hệ thống rồi in, kết quả vẫn chỉ là chữ đen trên giấy trắng; quan sát cho thấy các trình duyệt không áp dụng style chế độ tối đó khi in
- Trong thử nghiệm bổ sung, ở chế độ xem trước khi in,
prefers-color-scheme luôn được báo là light; điều này được xác nhận trên Firefox và Chromium
- Bài viết còn đùa rằng sẽ hơi tiếc nếu có chiếc máy in dùng giấy đen và mực trắng
1 bình luận
Ý kiến trên Hacker News
userContent.csscủa Firefox là khá ổn