10 คะแนน โดย GN⁺ 10 일 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • สรุปการแบ่ง 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 ในระดับถัดไปในระดับหนึ่ง
  • 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 ได้ด้วย ซึ่งความต่างนี้เปิดโอกาสให้ประยุกต์ใช้เพิ่มเติม
  • 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 เป็นเส้นขอบ ก็ล้วนทำได้ทั้งหมด
  • Level 5: Bisectional

    • media query ใช้ใน HTML ได้เช่นกัน โดยใส่ไว้ในแอตทริบิวต์ media ของ element link เพื่อแยก stylesheet ตาม scheme ได้
    • ตัวอย่างเสนอวิธีเชื่อม light.css และ dark.css เข้ากับ prefers-color-scheme: light และ prefers-color-scheme: dark ตามลำดับ
    • หากขอบเขตการปรับแต่งมีมาก การแยกเป็นไฟล์เฉพาะจะเหมาะสมกว่า และเบราว์เซอร์สามารถละเว้นไฟล์ CSS ที่ไม่ตรงกับ query ได้ จึงอาจลดจำนวนไฟล์ที่ต้องดาวน์โหลดลงหนึ่งไฟล์
  • Level 6: Ballistic

    • ใน JavaScript สามารถใช้ color scheme media query ได้ผ่าน window.matchMedia('(prefers-color-scheme:dark)')
    • สามารถ query ว่าเป็นโหมดสว่างหรือมืดได้แบบเดียวกับ 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 ให้เป็นค่าของโหมดมืดภายใต้ selector html:has(meta[name="color-scheme"][content="dark"])
    • จึงสามารถตรวจสอบธีมโดยอิงจาก meta element จริงได้ โดยไม่ต้องมีคลาสหรือ data attribute แยกต่างหาก

ประเด็นเพิ่มเติมและข้อสังเกต

  • ข้อสังเกตจาก 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
    • ปิดท้ายด้วยการแซวว่าคงน่าเสียดายถ้ามีเครื่องพิมพ์ที่ใช้กระดาษสีดำกับหมึกสีขาว

1 ความคิดเห็น

 
GN⁺ 10 일 전
ความเห็นจาก Hacker News
  • ถ้าปรับแต่งเยอะ การแยกไฟล์เฉพาะก็พอฟังขึ้นอยู่หรอก แต่คำอธิบายที่ว่า CSS ที่ไม่ตรงกับ media query จะไม่ถูกดาวน์โหลดเลยนั้น ผมว่ามันไม่ตรงกับการทำงานจริงของเบราว์เซอร์ จากประสบการณ์ของผม เบราว์เซอร์สุดท้ายก็ ดาวน์โหลดทั้งหมด อยู่ดี แค่ให้ลำดับความสำคัญต่างกัน
  • ผมสงสัยว่ายังไม่มีวิธีป้องกันอาการวาบสว่างแบบ flashbang ที่เกิดขึ้นระหว่างรอคอนเทนต์เริ่มต้นจากเซิร์ฟเวอร์จริง ๆ เหรอ
    • ผมว่าการกำหนด background-color ใน userContent.css ของ Firefox ก็ใช้ได้ดีนะ
    • ผมแค่ ลดความสว่างหน้าจอ แล้วปิดดาร์กโหมด อาการ flashbang ก็หายไปเอง แถมแบตเตอรี่อยู่ได้นานขึ้นด้วย
  • ตอนแรกผมนึกว่าบทความนี้จะพูดถึงความชอบเรื่อง ความดำของพื้นหลัง ในดาร์กโหมดเสียอีก ก็เคยได้ยินว่าดำสนิทช่วยประหยัดแบตบน OLED ได้ดีกว่า และผมก็รู้จักคนที่ชอบสีเทาที่หมึกไม่เข้มเท่าดำสนิทมากกว่าเหมือนกัน แต่จะต้องถึงหกระดับเลยไหมผมก็ยังไม่แน่ใจ ที่พอรู้สึกความต่างได้จริงสำหรับผมน่าจะมากสุดแค่ราว ๆ 3~4 ระดับ
    • ผมคิดว่าทางออกที่เป็นสากลกว่าคือการทำมาตรฐานความเข้ากันได้กับ Reader Mode แทนที่จะให้แต่ละเว็บต้องมารองรับรสนิยมผู้ใช้ทุกแบบจนกลายเป็นปัญหา n x m ผมว่าถ้าเว็บรองรับแค่มุมมองคอนเทนต์แบบเรียบง่ายหนึ่งแบบ แล้วให้เบราว์เซอร์จัดการการตั้งค่ารายผู้ใช้ต่อจากนั้น จะดีกว่า
    • สำหรับ OLED ผมค่อนข้างชอบ สีดำสนิท เพราะรู้สึกว่ายิ่งพิกเซลติดน้อย ภาระเรื่องเบิร์นอินก็ยิ่งลดลง และไหน ๆ อายุการใช้งานก็มีจำกัดอยู่แล้ว ในระยะยาวผมจึงอยากใช้จอให้นานกว่า 5 ปีขึ้นไป มากกว่าจะเปลี่ยนทุก 2~3 ปี
  • สำหรับผม ระดับที่ดีที่สุดคือ 9 ไม่ก็ 0 คือแค่ ปิดคอมพิวเตอร์ แล้วไป นอนหลับ
  • ผมดีใจที่ OP ทำ สวิตช์ 3 สถานะ ได้ถูกต้อง
  • ผมคิดว่าน่าจะสนุกกว่านี้ถ้าระดับต่าง ๆ ถูก ปรับใช้แบบไดนามิก ตอนเลื่อนหน้าลง
    • หรือไม่ก็ให้ผู้อ่านเลือก ระดับ เองได้ตามตำแหน่งที่เหมาะสมของหน้าแต่ละจุดก็น่าจะโอเค
  • ผมว่ามันน่าจะเป็น 8 ระดับ มากกว่านะ
  • มันให้ความรู้สึกว่า นี่มันปี 2024 จริง ๆ
  • ในสถานการณ์แบบนี้ สิ่งที่ผมนึกถึงก็คือ xkcd 3227 นั่นแหละ