ปุ่มสลับโหมดมืดช่วยให้ผู้ใช้ลบล้างรูปแบบสีของระบบสำหรับเว็บไซต์เดียวได้
การลบล้างจะมีผลโดยการอัปเดต <meta name="color-scheme">: light dark หมายถึง "ทำตามค่ากำหนดของระบบ" light หรือ dark ปักหมุดรูปแบบที่ชัดเจน
สี (light-dark()) สีของระบบ และ UI แบบเนทีฟทั้งหมดจะปิดพร็อพเพอร์ตี้ color-scheme ของ CSS ดังนั้นปุ่มเปิด/ปิดจึงทำงานโดยการซิงค์พร็อพเพอร์ตี้นั้นกับ <meta> (ดูแสดงการลบล้างใน CSS)
ปุ่มเปิด/ปิดแบบถาวร การควบคุมการตั้งค่า หรือไม่มีปุ่มเปิด/ปิดเลย
เว็บไซต์ส่วนใหญ่ไม่จำเป็นต้องมีปุ่มสลับรูปแบบสีแบบถาวรใน UI ของเว็บไซต์ (ส่วนหัว, การนำทาง, ส่วนท้าย ฯลฯ) ทำตามค่ากำหนดของระบบโดยค่าเริ่มต้น และหากจำเป็นต้องลบล้างด้วยตนเอง ให้วางตัวควบคุมไว้ในแพลตฟอร์มการตั้งค่าแยกต่างหาก เช่น หน้าการตั้งค่า แผง หรือการวางซ้อน
การปักหมุดรูปแบบกับระบบปฏิบัติการเป็นความตั้งใจที่ถูกต้องตามกฎหมายแต่เกิดขึ้นไม่บ่อยนัก และความตั้งใจที่เกิดขึ้นไม่บ่อยนักควรอยู่เบื้องหลังการเปิดเผยข้อมูลแบบต่อเนื่อง ไม่ใช่ในการควบคุมที่มองเห็นได้ตลอดเวลา
ปุ่มเปิด/ปิดแบบถาวรมักพบในเว็บไซต์ที่แสดงต่อนักพัฒนาซอฟต์แวร์หรือเว็บไซต์ที่เกี่ยวข้องกับนักพัฒนาซอฟต์แวร์ (เช่น สำหรับนักออกแบบ) ซึ่งการเปลี่ยนรูปแบบเป็นงานที่ทำบ่อยกว่าผู้ใช้เว็บทั่วไปมาก อย่าเพิ่มเพียงเพราะเป็นรูปแบบที่พบได้ทั่วไปในเว็บไซต์ของนักพัฒนาซอฟต์แวร์ เนื่องจากความสนใจของนักพัฒนาซอฟต์แวร์ในการควบคุมนี้ไม่ได้แสดงถึงผู้ใช้ทั่วไป
การใช้งาน
ก่อนอื่น ให้ทำตามขั้นตอนทั้งหมดในโหมดมืดเพื่อรองรับทั้ง 2 รูปแบบ โดยค่าเริ่มต้นจะเป็นค่ากำหนดของระบบ
โมเดลข้อมูล
โดยทั่วไปแล้ว โมเดลข้อมูลสำหรับการสลับโหมดมืดจะมี 3 สถานะ ได้แก่
- ระบบ (ไม่มีค่าที่จัดเก็บไว้): UI จะเป็นไปตามรูปแบบสีของระบบ ซึ่งควรเป็นค่าเริ่มต้น
- สว่าง (จัดเก็บเป็น
"light"): UI จะใช้ธีมสว่างไม่ว่ารูปแบบสีของระบบจะเป็นอย่างไร - มืด (จัดเก็บเป็น
"dark"): UI จะใช้ธีมมืดโดยไม่คำนึงถึงรูปแบบสีของระบบ
โดยปกติแล้วสถานะนี้จะจัดเก็บไว้ใน localStorage และแสดงในองค์ประกอบ <meta name="color-scheme"> ในส่วนหัวของเอกสาร
แสดงการลบล้างใน CSS
<meta> เป็นเพียงคำแนะนำในการนำเสนอ: การประกาศ color-scheme ใดๆ ใน CSS ของผู้เขียนจะลบล้างคำแนะนำดังกล่าว
เนื่องจากโหมดมืดตั้งค่า color-scheme: light dark ใน :root การอัปเดต <meta> เพียงอย่างเดียวจึงไม่มีผล เนื่องจาก CSS มีผลเหนือกว่า
แมป <meta> กลับไปยังพร็อพเพอร์ตี้เพื่อให้การเรียงซ้อนเป็นไปตามนั้น
:root {
color-scheme: light dark;
&:has(> head > meta[name="color-scheme"][content="dark"]) {
color-scheme: dark;
}
&:has(> head > meta[name="color-scheme"][content="light"]) {
color-scheme: light;
}
}
อย่าฮาร์ดโค้ด color-scheme: light หรือ color-scheme: dark เป็นค่าเริ่มต้นของรูท การประกาศฐานต้องเป็น light dark
CSS ต้องไม่ขึ้นอยู่กับ JS: หาก JS ไม่เคยทำงาน <meta> จะยังคงเป็น light dark และเว็บไซต์จะเป็นไปตามค่ากำหนดของระบบ โดยไม่มีอะไรเสียหาย
การคงอยู่และการป้องกัน FOUC
คงการลบล้างไว้ใน localStorage และนำรายการออกเมื่อกลับไปใช้ค่าเริ่มต้นของระบบ
หากต้องการหลีกเลี่ยงการแสดงธีมที่ไม่ถูกต้อง ให้ใช้ค่าที่จัดเก็บไว้ในสคริปต์ในบรรทัด (ไม่ใช่ type=module และไม่ใช่ defer) ซึ่งวางไว้ต่อจากองค์ประกอบ <meta> ทันที ดังนี้
<meta name="color-scheme" content="light dark">
<script>
document.querySelector('meta[name="color-scheme"]').content = localStorage.getItem("color-scheme") ?? "light dark";
</script>
- สคริปต์ในบรรทัดนี้มีไว้เพื่อป้องกัน FOUC เท่านั้น ทำให้มีขนาดเล็กที่สุดเท่าที่จะเป็นไปได้ โดย JS เพิ่มเติมสำหรับการจัดการการสลับรูปแบบสีจะโหลดในภายหลังได้
- ในบางกรณีที่เกิดขึ้นไม่บ่อยนัก การเข้าถึง
localStorageอาจทำให้เกิดข้อผิดพลาด (เช่น ข้อมูลเว็บไซต์ถูกบล็อก) แต่เนื่องจากสคริปต์นี้ไม่ได้ทำอะไรอย่างอื่น ผลข้างเคียงเพียงอย่างเดียวคือข้อผิดพลาดในคอนโซล รวมในtry .. catchหากเป็นเรื่องสำคัญ ตรวจสอบว่ายังคงใช้ธีมกับหน้าเว็บอยู่ แม้ว่าจะไม่สามารถคงธีมไว้ได้ก็ตาม - การลบล้างสามารถเปลี่ยนจากแท็บอื่นได้: จัดการเหตุการณ์
storageของwindowเพื่อให้ซิงค์อยู่เสมอ - อย่าใช้
matchMedia()เพื่อนำค่าที่จัดเก็บไว้ออกเมื่อค่ากำหนดของระบบเปลี่ยนไปตรงกับค่านั้น ระบบปฏิบัติการของผู้ใช้หลายรายจะเปลี่ยนรูปแบบโดยอัตโนมัติตามช่วงเวลาของวัน การนำค่าที่จัดเก็บไว้ออกเมื่อทั้ง 2 อย่างเกิดขึ้นพร้อมกันจะทำให้ปักหมุดรูปแบบไม่ได้เลย
การแยกสาขาสำหรับ HTML และค่าที่ไม่ใช่สี
คุณไม่ต้องดำเนินการใดๆ เพิ่มเติมเกี่ยวกับสี เนื่องจากเมื่อจับคู่ <meta> กับ color-scheme (ด้านบน) แล้ว light-dark() จะเป็นไปตามการลบล้าง
ส่วนนี้เกี่ยวกับการปรับค่าอื่นๆ (เช่น font-weight, แหล่งที่มาของสื่อ ฯลฯ)
เมื่อหน้าเว็บเป็นไปตามค่ากำหนดของระบบ คุณสามารถใช้ (prefers-color-scheme: dark) สำหรับการแยกสาขา รวมถึงในแหล่งที่มา <picture> หรือ <video>
การลบล้างรูปแบบสีจะเพิ่มความซับซ้อนมากขึ้น เนื่องจากค่ากำหนดของระบบจะไม่ใช่แหล่งข้อมูลที่ถูกต้องอีกต่อไป และสำหรับ API ที่ยอมรับเฉพาะคิวรี่สื่อจะไม่มีทางเลือกอื่นโดยตรง
อย่าพึ่งพาคลาสที่ใช้ JS เช่น .dark สำหรับการแยกสาขาเพียงอย่างเดียว เนื่องจากคลาสเหล่านี้จะไม่ถูกต้องหาก JS ไม่โหลดและค่าเริ่มต้นของระบบปฏิบัติการเป็นโหมดมืด
คุณสามารถรวมการสืบค้นสื่อกับตัวเลือก :root:has(> head > meta[name="color-scheme"][content="dark"]) (หรือ light) เพื่อแยกสาขาได้
ดูรายละเอียดเกี่ยวกับวิธีใช้ตัวเลือกนี้อย่างมีประสิทธิภาพได้ที่ชุดค่าผสมของตัวเลือกและ @-rule
ตัวเลือกของตัวควบคุมเองก็เป็นสาขาที่ไม่มีสีเช่นกัน โดยรวมทั้ง 2 สถานะไว้ในมาร์กอัป (ไอคอนบวกข้อความการดำเนินการที่ซ่อนอยู่ เช่น "เปลี่ยนเป็นธีมมืด") และซ่อนสถานะที่ไม่ได้ใช้งานผ่านตัวเลือกเหล่านี้
display: none ยังนำตัวเลือกที่ซ้ำซ้อนออกจาก AT ด้วย ดังนั้นการควบคุมจึงไม่จำเป็นต้องใช้ JS เพื่อให้เป็นปัจจุบันเมื่อค่ากำหนดของระบบเปลี่ยนแปลง
สำหรับสื่อใน HTML วิธีเดียวในตอนนี้คือการรวมทั้ง 2 เวอร์ชันเป็นองค์ประกอบแยกต่างหากและสลับระดับการเข้าถึงอย่างเหมาะสม
การซ่อนองค์ประกอบ <source> ด้วย display: none ไม่ทำงาน
อินเทอร์เฟซผู้ใช้
2 หรือ 3 รัฐ
ในทุกกรณี UI ต้องรองรับการเปลี่ยนกลับหรือตั้งค่ารูปแบบสีเป็นระบบ
แนะนำให้แสดง 2 สถานะในปุ่มเปิด/ปิดที่มีพื้นที่จำกัด เช่น ปุ่มเปิด/ปิดแบบถาวรใน Chrome ของเว็บไซต์ (ส่วนหัว, การนำทาง, ส่วนท้าย ฯลฯ) ซึ่งมีพื้นที่จำกัดและการปรับแต่งการตั้งค่ามักจะไม่เกี่ยวข้องกับเป้าหมายของผู้ใช้
การควบคุมรูปแบบสีในแพลตฟอร์มการตั้งค่าแยกต่างหาก (หน้า แผง หรือการวางซ้อน) เป็นสถานการณ์ที่แตกต่างกัน และอาจแสดงทั้ง 3 สถานะอย่างชัดเจน ("สว่าง" "มืด" "ระบบ") ซึ่งในกรณีนี้ ผู้ใช้ได้ตัดสินใจอย่างรอบคอบเกี่ยวกับลักษณะการทำงานในอนาคตแล้ว และมีพื้นที่สำหรับอธิบายตัวเลือกต่างๆ
นอกจากนี้ยังรับประกันสถานะที่ชัดเจน 3 สถานะหากเว็บไซต์ใช้รูปแบบที่คำนึงถึงบริบท (เช่น โหมดแสงที่หรี่ลงเมื่อระบบปฏิบัติการมืด) เนื่องจาก "สว่าง" และ "ระบบ (สว่างอยู่)" จะแตกต่างกันอย่างแท้จริง
ปุ่มสลับ 2 สถานะ
เมื่อใช้การควบคุมดังกล่าว มักจะเป็นการปรับความสบายชั่วคราว ("ตอนนี้สว่างเกินไป") แทนที่จะเป็นการตรวจสอบว่าสถานะปัจจุบันได้รับการคงไว้ในระยะยาว ดังนั้น สำหรับปุ่มเปิด/ปิด 2 สถานะ การแสดงการตั้งค่า 2 ใน 3 รายการก็เพียงพอแล้ว ได้แก่ ระบบ (เพื่อให้เปลี่ยนการตั้งค่ากลับได้) และค่าตรงข้ามปัจจุบันของระบบ ซึ่งจัดเก็บเป็นค่าลิเทอรัลปัจจุบัน
สถานะทั้ง 2 สถานะควรเป็นดังนี้
- ค่าเริ่มต้นของระบบ - ไม่มีค่าที่จัดเก็บไว้, เนื้อหา
<meta>light darkแสดงเป็นค่าที่แก้ไขแล้วในปัจจุบัน (เช่น ไอคอนดวงอาทิตย์เมื่อสว่าง) - ลบล้าง - จัดเก็บตามตัวอักษรเป็น
lightหรือdark
โดยพื้นฐานแล้ว การควบคุมนี้เป็นแบบ 3 สถานะ (light dark, light, dark) ซึ่งสถานะที่ชัดเจนซึ่งตรงกับค่ากำหนดของระบบปัจจุบันไม่สามารถเข้าถึงได้
เมื่อผู้ใช้สลับตัวเลือก
- รูปแบบเป้าหมาย = ตรงข้ามกับรูปแบบที่แสดงผลอยู่ในปัจจุบัน (ค่าที่จัดเก็บไว้ หากมี หรือค่ากำหนดของระบบ) ความตั้งใจของผู้ใช้คือ "เลือกสิ่งที่ตรงข้ามกับที่ฉันเห็นอยู่ขณะนี้" ไม่ใช่ "เลือกสิ่งที่ตรงข้ามกับค่าเริ่มต้นของระบบ"
- หากเป้าหมายแตกต่างจากค่ากำหนดของระบบปัจจุบัน ให้จัดเก็บตามตัวอักษร
- หากเป้าหมายตรงกับค่ากำหนดของระบบปัจจุบัน แสดงว่าผู้ใช้กำลังยกเลิกการปรับเปลี่ยน ให้นำค่าที่จัดเก็บไว้ออก อย่าจัดเก็บไว้ เพราะจะทำให้รูปแบบดังกล่าวถูกปักหมุดไว้โดยไม่แสดงให้เห็นเพื่อป้องกันการเปลี่ยนแปลงระบบในอนาคต
- ตั้งค่าเนื้อหา
<meta>เป็นค่าที่จัดเก็บไว้ หรือlight darkหากไม่มี
สำคัญ: ต้องตรวจสอบความแตกต่างเฉพาะในเวลาที่จัดเก็บเท่านั้น ไม่สามารถตรวจสอบย้อนหลังได้ โดยต้องเก็บค่าที่จัดเก็บไว้ซึ่งค่ากำหนดของระบบเปลี่ยนให้ตรงกันในภายหลัง ระบบปฏิบัติการของผู้ใช้หลายรายจะเปลี่ยนรูปแบบโดยอัตโนมัติตามช่วงเวลาของวัน การนำค่าที่จัดเก็บไว้ออกเมื่อทั้ง 2 อย่างเกิดขึ้นพร้อมกันจะทำให้ปักหมุดรูปแบบไม่ได้เลย
ตัวอย่างสถานการณ์ โดยเริ่มจากระบบปฏิบัติการที่ตั้งค่าเป็นธีมสว่าง
- ผู้ใช้สลับ ธีมมืดแตกต่างจากค่ากำหนดของระบบ ระบบจึงจัดเก็บ
darkไว้ และเว็บไซต์จะเปลี่ยนเป็นธีมมืด - การตั้งค่าระบบปฏิบัติการจะเปลี่ยนเป็นโหมดมืด เว็บไซต์จะยังคงเป็นสีมืด (ค่าที่จัดเก็บไว้ตรงกับค่ากำหนดของระบบ แต่จะยังคงอยู่)
- การตั้งค่าระบบปฏิบัติการจะเปลี่ยนกลับเป็นธีมสว่าง เว็บไซต์จะยังคงเป็นสีมืด
- ผู้ใช้สลับ เป้าหมาย (สว่าง) ตรงกับค่ากำหนดของระบบ ระบบจึงนำค่าที่จัดเก็บไว้ออกและเว็บไซต์จะทำตามระบบอีกครั้ง
ปุ่มสลับ 3 สถานะ
เมื่อมีพื้นที่มากขึ้นและผู้ใช้มีแนวคิดในการตั้งค่ากำหนดระยะยาวอยู่แล้ว การควบคุมแบบ 3 สถานะจะช่วยให้มีความชัดเจนมากขึ้น ในกรณีนี้ โมเดลข้อมูลจะแมปกับตัวเลือก UI 3 รายการอย่างชัดเจน ได้แก่ ระบบ สว่าง และมืด
เพื่อลดภาระการรับรู้ ตัวเลือก "ระบบ" ควรแสดงการตั้งค่าระบบปัจจุบันด้วย เช่น ผ่านทาง:
- ไอคอน เช่น ไอคอนดวงอาทิตย์ที่ด้านขวาล่างของไอคอนระบบ
- ข้อความ เช่น "ระบบ (ปัจจุบันเป็นธีมสว่าง)"