หกระดับของ Dark Mode (2024)
(cssence.com)- สรุปการแบ่ง 8 ระดับ ของการขยายขอบเขตการทำ Dark Mode แบบค่อยเป็นค่อยไป ตั้งแต่ฟีเจอร์พื้นฐานของเบราว์เซอร์ไปจนถึง JavaScript media query
- วิธีที่ง่ายที่สุดคือประกาศ
<meta name="color-scheme" content="light dark">หรือcolor-scheme: light darkเพียงอย่างเดียว เพื่อให้ทำงานตาม ความชอบ color scheme ของผู้ใช้ - ในระดับที่สูงขึ้น สามารถใช้ฟังก์ชัน
light-dark(),@media (prefers-color-scheme: dark), และ stylesheet แยกตาม scheme เพื่อปรับแต่งได้กว้างตั้งแต่สีไปจนถึงรูปภาพและเงา - สามารถสร้างตัวสลับที่ไม่ได้อิงแค่การตั้งค่าระบบของผู้ใช้ โดยมี 3 ตัวเลือกคือ Automatic·light·dark และใช้
:has()กับ meta element จริงในการตรวจสอบธีมได้ - รวมถึง ข้อจำกัดด้านการเข้าถึง ของ Safari และการสังเกตพฤติกรรมของ
prefers-color-schemeระหว่างการพิมพ์ ซึ่งแสดงให้เห็นว่าฟีเจอร์ CSS รุ่นใหม่ทำให้การรองรับโหมดสว่าง·มืดในตัวทำได้ง่ายขึ้นมาก
การทำ Dark Mode แบบแยกตามระดับ
-
Level 1: Barebone
- เปิดใช้การแยก light/dark ได้แม้ไม่มี CSS เลย เพียงเพิ่ม
<meta name="color-scheme" content="light dark">ใน head ของเอกสาร เบราว์เซอร์ก็จะเริ่มทำงานตาม ความชอบ color scheme ของผู้ใช้ - ตามทฤษฎีแล้ว ลำดับของรายการในแอตทริบิวต์
contentมีความหมาย โดยผู้ใช้ที่ไม่ได้ระบุความชอบ color scheme จะได้รับค่าตัวแรกในรายการที่คั่นด้วยช่องว่าง - ปัจจุบันการตั้งค่าระบบปฏิบัติการไม่มีตัวเลือกให้ไม่เลือก color scheme ดังนั้นในทางปฏิบัติจึงลงเอยด้วย scheme ที่ตรงกับการตั้งค่าของระบบปฏิบัติการ
- สามารถกำหนดค่าเดียวใน
contentได้เช่นกัน ซึ่งในกรณีนั้นจะบังคับใช้ scheme ดังกล่าวโดยไม่สนใจความชอบของผู้ใช้ - meta tag นี้ทำหน้าที่เป็น วิธีฝั่ง HTML ที่สอดคล้องกับวิธีแบบ CSS ในระดับถัดไปในระดับหนึ่ง
- เปิดใช้การแยก light/dark ได้แม้ไม่มี CSS เลย เพียงเพิ่ม
-
Level 2: Basic
- ใน CSS สามารถใช้
html { color-scheme: light dark; }เพื่อเปิดใช้การแยก โหมดสว่าง/มืด ได้ - หากมี meta tag อยู่ใน DOM แล้ว ก็ไม่จำเป็นต้องใช้ประกาศนี้ และหากควบคุม HTML ได้ แนะนำให้ใช้ meta tag เพราะเบราว์เซอร์จะรู้คำสั่งได้ตั้งแต่ก่อน parse CSS
- ทั้งสองวิธีทำให้สามารถใช้สไตล์พื้นฐานของ user agent และ โหมดสว่าง/มืด ที่รวมอยู่ในนั้นได้
- หากเพิ่ม CSS เข้าไป แต่จำกัดให้เน้นใช้ CSS system colors ก็สามารถทำดีไซน์ที่ดูเป็นระเบียบได้พอสมควร
- ต่างจาก meta tag ที่มีผลกับทั้งเอกสารเสมอ การประกาศ
color-schemeใน CSS สามารถกำหนดไว้ตำแหน่งอื่นที่ไม่ใช่ root element ได้ด้วย ซึ่งความต่างนี้เปิดโอกาสให้ประยุกต์ใช้เพิ่มเติม
- ใน CSS สามารถใช้
-
Level 3: Benign
- สามารถปรับโหมดสว่าง/มืดแบบง่าย ๆ ได้ด้วยฟังก์ชันสี
light-dark()ของ CSS ที่เพิ่มเข้ามาไม่นานนี้ - ในตัวอย่างใช้แบบ
background-color: light-dark(black, white);และcolor: light-dark(white, black);โดยอาร์กิวเมนต์ตัวแรกจะใช้กับโหมดสว่าง และตัวที่สองจะใช้กับโหมดมืด - ในอาร์กิวเมนต์สามารถใส่สีจริงโดยตรง หรือใส่ custom properties ที่ตีความเป็นสีก็ได้
- ทั้งบทความนี้มีเพียงระดับนี้เท่านั้นที่ ณ เวลาที่เขียนยังมี การรองรับของเบราว์เซอร์ ไม่เพียงพอ
- สามารถปรับโหมดสว่าง/มืดแบบง่าย ๆ ได้ด้วยฟังก์ชันสี
-
Level 4: Bold
- สามารถทำการสลับ Dark Mode ได้ด้วย media query แบบดั้งเดิม
@media (prefers-color-scheme: dark) - ไม่ว่าจะ query ฝั่ง
lightหรือdarkก็สามารถปรับแต่งได้ในระดับสูงสุด ไม่ได้จำกัดแค่การเปลี่ยนสีอย่างเดียว - ไม่ว่าจะเป็นการทำให้รูปภาพมีความอิ่มสีน้อยลงด้วย filter ในโหมดมืด หรือเปลี่ยน box shadow เป็นเส้นขอบ ก็ล้วนทำได้ทั้งหมด
- สามารถทำการสลับ Dark Mode ได้ด้วย media query แบบดั้งเดิม
-
Level 5: Bisectional
- media query ใช้ใน HTML ได้เช่นกัน โดยใส่ไว้ในแอตทริบิวต์
mediaของ elementlinkเพื่อแยก stylesheet ตาม scheme ได้ - ตัวอย่างเสนอวิธีเชื่อม
light.cssและdark.cssเข้ากับprefers-color-scheme: lightและprefers-color-scheme: darkตามลำดับ - หากขอบเขตการปรับแต่งมีมาก การแยกเป็นไฟล์เฉพาะจะเหมาะสมกว่า และเบราว์เซอร์สามารถละเว้นไฟล์ CSS ที่ไม่ตรงกับ query ได้ จึงอาจลดจำนวนไฟล์ที่ต้องดาวน์โหลดลงหนึ่งไฟล์
- media query ใช้ใน HTML ได้เช่นกัน โดยใส่ไว้ในแอตทริบิวต์
-
Level 6: Ballistic
- ใน JavaScript สามารถใช้ color scheme media query ได้ผ่าน
window.matchMedia('(prefers-color-scheme:dark)') - สามารถ query ว่าเป็นโหมดสว่างหรือมืดได้แบบเดียวกับ media query อื่น ๆ แล้วนำผลไปใช้ทำงานตามต้องการ
- ในการใช้งานจริง ไม่จำเป็นต้องยึดเพียงเทคนิคจากระดับก่อนหน้าแบบใดแบบหนึ่ง แต่สามารถ ผสมหลายวิธี เข้าด้วยกันได้
- ใน JavaScript สามารถใช้ color scheme media query ได้ผ่าน
ตัวสลับของผู้ใช้และแพตเทิร์นขั้นสูง
-
Level 7: Beyond
- ไม่จำเป็นต้องพึ่งแต่ค่าความชอบของระบบผู้ใช้เท่านั้น แต่สามารถสร้าง color scheme switcher ได้
- ตัวสลับนี้ไม่ใช่แค่ค่า boolean ธรรมดา เพราะควรมีโหมด Automatic ที่ใช้
prefers-color-schemeเป็นค่าเริ่มต้น - เมื่อวางตัวสลับทับลงไป ผู้ใช้จะเลือกได้หนึ่งใน สามโหมด คือ Automatic, light, dark
-
Level 8: Beguiling
- เวลาทำตัวสลับแบบ Level 7 โดยทั่วไปมักใช้วิธีเพิ่มคลาส
.darkหรือแอตทริบิวต์อย่างdata-theme="dark"ให้กับ element HTML - แต่อีกทางเลือกคือใช้
:has()เพื่อ query การมีอยู่จริงของ<meta name="color-scheme" content="dark">ได้โดยตรง - ในตัวอย่าง มีการตั้ง ตัวแปร CSS เช่น
--color-bg,--color-textให้เป็นค่าของโหมดมืดภายใต้ selectorhtml:has(meta[name="color-scheme"][content="dark"]) - จึงสามารถตรวจสอบธีมโดยอิงจาก meta element จริงได้ โดยไม่ต้องมีคลาสหรือ data attribute แยกต่างหาก
- เวลาทำตัวสลับแบบ Level 7 โดยทั่วไปมักใช้วิธีเพิ่มคลาส
ประเด็นเพิ่มเติมและข้อสังเกต
-
ข้อสังเกตจาก CSS Naked Day
- หลังจากลบสไตล์ออก พบว่าแทบทุกเว็บไซต์ที่เข้าเยี่ยมชม ไม่มี Dark Mode อย่างชัดเจน และนั่นนำไปสู่การแบ่งระดับของ Dark Mode นี้
- มีการกล่าวด้วยว่า หากกำลังสร้างเว็บไซต์ใหม่ตั้งแต่ต้นและเขียนสไตล์ขึ้นมาใหม่ ฟีเจอร์ CSS สมัยใหม่ทำให้การมี โหมดสว่าง/มืดในตัว เป็นเรื่องง่ายมาก
-
ปัญหาการเข้าถึงใน Safari
- มีการชี้ว่า จนกระทั่งไม่นานมานี้ Safari ยังไม่ให้ สีลิงก์ที่เข้าถึงได้ ในโหมดมืด
- ใน CSS Naked Day ครั้งก่อน ผู้เขียนเคยพบปัญหานี้และลบ meta tag ออก แล้วใช้เฉพาะ color scheme แบบสว่าง
- หลังจากนั้นได้เพิ่ม meta tag กลับเข้าไปอีกครั้ง แต่ก็รับรู้ว่าผู้ใช้ Safari เวอร์ชันเก่าอาจเจอ การเข้าถึงที่ลดลง ได้
- ยังพบด้วยว่าใน Dark Mode ของ Safari กล่องข้อความ ไม่มีเส้นขอบที่มองเห็นได้
- สไตล์จาก user agent เพียงอย่างเดียว แม้จะใช้ semantic HTML อย่างถูกต้อง ก็ยังไม่อาจรับประกันการเข้าถึงได้ครบถ้วน จึงมีการพิจารณาว่าใน CSS Naked Day ครั้งต่อไปควรคงสไตล์ไว้มากพอ
-
การพิมพ์และเงื่อนไข
screen and- ในตัวอย่าง Bisectional มีการกล่าวว่าที่ใช้
screen and ...ก็เพื่อ ยกเว้นเป้าหมายที่เป็นเครื่องพิมพ์ - โดยตั้งสมมติฐานว่ามี core stylesheet ที่ไม่ขึ้นกับธีม หรือมี stylesheet สำหรับการพิมพ์โดยเฉพาะอยู่แล้ว และเนื่องจาก Dark Mode บนเครื่องพิมพ์อาจใช้หมึกมาก จึงเลือกแยกไว้เพื่อความปลอดภัย
- จากการทดสอบจริง แม้จะพิมพ์ขณะเปิดโหมดมืดของระบบอยู่ ก็ยังได้ผลเป็นข้อความสีดำบนกระดาษขาวเท่านั้น และสังเกตว่าเบราว์เซอร์ไม่ได้ใช้สไตล์ Dark Mode ดังกล่าวกับการพิมพ์
- ในการทดสอบเพิ่มเติม พบว่าในหน้าตัวอย่างก่อนพิมพ์
prefers-color-schemeจะถูกรายงานเป็น light เสมอ โดยตรวจสอบใน Firefox และ Chromium - ปิดท้ายด้วยการแซวว่าคงน่าเสียดายถ้ามีเครื่องพิมพ์ที่ใช้กระดาษสีดำกับหมึกสีขาว
- ในตัวอย่าง Bisectional มีการกล่าวว่าที่ใช้
1 ความคิดเห็น
ความเห็นจาก Hacker News
userContent.cssของ Firefox ก็ใช้ได้ดีนะ