แม้ว่าโดยทั่วไปจะตั้งค่าในรูท แต่คุณสามารถตั้งค่าพร็อพเพอร์ตี้ color-scheme ในองค์ประกอบแต่ละรายการเพื่อบังคับให้องค์ประกอบเหล่านั้นใช้รูปแบบสีที่แตกต่างจากส่วนอื่นๆ ของหน้าได้
ซึ่งจะเป็นประโยชน์สำหรับคอมโพเนนต์ที่ต้องดูในรูปแบบสีที่เฉพาะเจาะจงเสมอ (เช่น ในโหมดมืดหรือโหมดสว่างเสมอ)
ตัวอย่างกรณีการใช้งานมีดังนี้
- องค์ประกอบที่มักอยู่ในโหมดมืดแม้ในหน้าโหมดสว่างด้วยเหตุผลด้านความสวยงาม เช่น บล็อกโค้ด มีเดียเพลเยอร์ แกลเลอรีรูปภาพ
- พื้นที่ที่มีสื่อซึ่งออกแบบมาสำหรับพื้นหลังสีอ่อน (เช่น รูปภาพ วิดีโอ ภาพประกอบ ตัวอย่างก่อนพิมพ์) สามารถตั้งค่าเป็นโหมดสว่างได้แม้ว่าส่วนที่เหลือของหน้าจะอยู่ในโหมดมืดก็ตาม
- องค์ประกอบที่รูปแบบสีควบคุมโดยการตั้งค่าระดับผู้ใช้ เช่น ตัวอย่างคอมโพเนนต์
- การฝังที่ไม่รองรับทั้งโหมดสว่างและโหมดมืด
- เครื่องมือออกแบบ แผนที่ การแสดงข้อมูลผ่านภาพ เกม ฯลฯ
ควรเปลี่ยนสีเมื่อใดและควรบังคับใช้ color-scheme เมื่อใด
ไม่ใช่องค์ประกอบทุกอย่างที่ใช้ข้อความสีอ่อนบนพื้นหลังสีเข้มในโหมดสว่างหรือข้อความสีเข้มบนพื้นหลังสีอ่อนในโหมดมืดจะต้องมี color-scheme ที่แตกต่างกัน
ตัวอย่างเช่น ปุ่มหลักอาจแสดงเป็นสีน้ำเงินพร้อมข้อความสีขาวในโหมดสว่าง แต่ไม่ได้หมายความว่าจะมี color-scheme: dark
โดยทั่วไปแล้ว องค์ประกอบที่ใช้ color-scheme ต่างกันจะเป็นพื้นผิวที่ซับซ้อนซึ่งสร้างบริบทภาพของตนเอง ไม่ใช่คอนเทนเนอร์แบบตื้นๆ ที่เรียบง่าย
เมื่อพิจารณาใช้ color-scheme อื่นในองค์ประกอบ ให้ถามตัวเองดังนี้
- UI ของเบราว์เซอร์ในตัวที่ไม่ได้ปรับแต่ง (เช่น ตัวควบคุมแบบฟอร์ม แถบเลื่อน ฯลฯ) ควรใช้รูปแบบสีนั้นหรือปรับให้เข้ากับรูปแบบสีของหน้าเว็บไหม -> if the former, don't use
color-scheme. - สี
light-dark()ควรแสดงผลเหมือนกับสีอื่นๆ ในหน้าเว็บหรือตามการลบล้าง -> if the former, don't usecolor-scheme. - ควรให้ผู้สืบทอดอยู่ใน
color-schemeนั้นไหม หากไม่มีเจาะจง อย่าใช้color-scheme
การติดตั้งใช้งานขั้นพื้นฐาน
โดยทั่วไปแล้ว (แม้ว่าจะไม่จำเป็นอย่างเคร่งครัด) ระบบจะใช้การลบล้างเฉพาะคอมโพเนนต์ในหน้าเว็บที่รองรับรูปแบบสีหลายรูปแบบผ่าน color-scheme ส่วนกลางด้วย
ดูวิธีใช้โหมดมืดทั่วทั้งหน้าเว็บอย่างมีประสิทธิภาพได้ที่โหมดมืด
เมื่อมี color-scheme ทั่วทั้งหน้า และคุณใช้โทเค็นสีที่ไวต่อโทเค็นดังกล่าว (เช่น ผ่าน light-dark()) คุณสามารถตั้งค่า color-scheme ในคอมโพเนนต์ที่เฉพาะเจาะจงเพื่อลบล้างโหมดสีสำหรับซับทรีนั้นได้ ดังนี้
pre, code, .dark {
color-scheme: dark;
}
โปรดทราบว่าเบราว์เซอร์บางรายการจะปรับคอมโพเนนต์ให้เข้ากับรูปแบบสีอื่นโดยอัตโนมัติอยู่แล้ว
หากต้องการบังคับใช้รูปแบบสีที่ระบุในทุกกรณี ให้ใช้ only เช่น color-scheme: only dark; แทน color-scheme: dark;
การปรับค่าที่ไม่ใช่สี
ปัจจุบัน light-dark() ใช้ได้กับสีเท่านั้น
แนวทางปฏิบัติแนะนำ
- บังคับ: อย่าตั้งค่า
color-schemeในองค์ประกอบที่ไม่มีพื้นหลัง เนื่องจากอาจทำให้เกิดการผสมคู่สีพื้นหลังและสีข้อความจากรูปแบบสีที่ต่างกัน ซึ่งส่งผลให้ข้อความอ่านไม่ได้ - ไม่บังคับ: แม้ว่าการใช้คู่สีเดียวกันกับโหมดมืดทั้งหน้าจะง่ายกว่า แต่เราสามารถกำหนดคู่สีที่แตกต่างกันสำหรับคอมโพเนนต์เหล่านี้ได้ ตัวอย่างเช่น เราอาจต้องการให้คอมโพเนนต์โหมดมืดที่ใช้ในหน้าโหมดสว่างมีความมืดน้อยกว่าเมื่อใช้คอมโพเนนต์โหมดมืดเดียวกันในหน้าเว็บที่โดยรวมเป็นโหมดมืด
ปัญหาที่ทราบซึ่งควรคำนึงถึง
ข้อควรระวัง: การรับค่าสี light-dark()
light-dark() จะได้รับการแก้ไขเมื่อถึงเวลาที่คำนวณค่า
ซึ่งหมายความว่าพร็อพเพอร์ตี้ <color> ที่รับค่ามาซึ่งตั้งค่าเป็นสี light-dark() จะส่งต่อสีใดสีหนึ่งจาก 2 สีไปยังองค์ประกอบสืบทอดเท่านั้น ไม่ใช่ตัวนิพจน์ light-dark() เอง
ซึ่งรวมถึงเนื้อหาต่อไปนี้
- พร็อพเพอร์ตี้สีในตัวที่รับค่ามา เช่น
color,accent-color,fill,stroke,text-shadow,caret-color - คุณสมบัติที่กำหนดเองซึ่งรับค่าได้ที่ลงทะเบียนไว้ซึ่งมี
syntax: <color>และinherits: true - ตั้งค่าพร็อพเพอร์ตี้
<color>อื่นๆ เป็นinherit
ซึ่งหมายความว่าคุณควรทำดังนี้
- อย่าลงทะเบียนคุณสมบัติที่กำหนดเองซึ่งมีไว้เพื่อเก็บโทเค็นการออกแบบ (เช่น
--surface-color) เป็น<color>โทเค็นต้องคงนิพจน์light-dark()ไว้เพื่อให้องค์ประกอบสืบทอดสามารถแก้ไขนิพจน์ดังกล่าวอีกครั้งภายใต้color-schemeอื่น - เมื่อตั้งค่า
color-schemeในองค์ประกอบ ให้ระบุพร็อพเพอร์ตี้<color>ที่รับค่ามาอีกครั้งซึ่งอาจตั้งค่าเป็นค่าlight-dark()(โดยตรงหรือผ่านโทเค็นการออกแบบ) แม้ว่าจะเป็นโทเค็นการออกแบบเดียวกันก็ตาม - ไม่ใช้
inheritกับพร็อพเพอร์ตี้<color>ในองค์ประกอบที่มีการลบล้างcolor-scheme(ใช้กับองค์ประกอบสืบทอดได้) - ควรใช้พร็อพเพอร์ตี้
<color>ที่ลงทะเบียนไว้สำหรับกรณีการใช้งานที่ตรงกันข้าม นั่นคือเมื่อคุณต้องการสแนปชอตสีที่แก้ไขแล้วของระดับบนสุดโดยเจตนา และป้องกันไม่ให้มีการแก้ไขอีกครั้งภายใต้color-schemeของระดับล่างสุด เช่น การจับภาพพื้นหลังของหน้าเพื่อใช้ที่อื่น - หากต้องการทำให้สีเคลื่อนไหว ให้ใช้พร็อพเพอร์ตี้
<color>ที่ลงทะเบียน@propertyแยกต่างหากในองค์ประกอบที่เคลื่อนไหว (ต้องลงทะเบียนสำหรับการประมาณค่าสี) ซึ่งไม่ใช่โทเค็นการออกแบบ แต่เป็นเป้าหมายภาพเคลื่อนไหวต่อองค์ประกอบ จึงไม่ขัดแย้งกับกฎข้างต้น
ตัวอย่าง
:root {
--accent-color: light-dark(blue, skyblue);
--surface-color: light-dark(white, #222);
--text-color: light-dark(#111, white);
color-scheme: light dark;
accent-color: var(--accent-color);
color: var(--text-color);
}
body {
/* --surface-color dynamically switches despite being inherited because --surface-color is not registered */
background: var(--surface-color);
}
pre, code {
color-scheme: dark;
background: var(--surface-color);
/* Without this, accent-color would be blue, not skyblue! */
accent-color: var(--accent-color);
/* Without this, text-color would be #111, not white! */
color: var(--text-color);
}
ปัญหาที่ควรทราบเมื่อใช้รูปแบบสี
- Chrome และ Firefox จะใช้
color-schemeสำหรับ iframe โดยจะแสดงผลหน้าที่ฝังในรูปแบบสีที่ถูกต้องและปรับการค้นหาสื่อprefers-color-schemeของหน้าที่ฝังเพื่อแสดงcolor-schemeของบริบทการฝัง แต่ Safari ไม่รองรับ และจะแปลงprefers-color-schemeเป็นการตั้งค่าระบบแม้จะอยู่ภายใน iframe- หากคุณควบคุมทั้งระดับบนสุดและ iframe: ให้ส่งรูปแบบสีของระดับบนสุดไปยัง iframe อย่างชัดเจนผ่านพารามิเตอร์ของ URL (
?theme=dark) ณ เวลาที่สร้าง iframe หรือผ่านpostMessage()(ซึ่งช่วยให้คุณตอบสนองต่อการเปลี่ยนแปลงรันไทม์ได้ด้วย) ใน iframe ให้ตั้งค่าคลาสใน<html>(และ/หรือcolor-schemeใน:root) จากสัญญาณนั้นแทนที่จะใช้prefers-color-scheme - หากคุณควบคุมเฉพาะหน้าที่ฝัง: ไม่มีวิธีที่เชื่อถือได้ในการตรวจหา
color-schemeของบริบทการฝังจากภายใน iframe ใน Safari แสดงพารามิเตอร์ธีมที่ชัดเจนใน API การฝัง (เช่น สตริงการค้นหาหรือโปรโตคอลpostMessage) และจัดทำเอกสารสำหรับผู้ฝัง
- หากคุณควบคุมทั้งระดับบนสุดและ iframe: ให้ส่งรูปแบบสีของระดับบนสุดไปยัง iframe อย่างชัดเจนผ่านพารามิเตอร์ของ URL (
กลยุทธ์สำรอง
การรองรับรูปแบบสีของเบราว์เซอร์และโหมดสำรอง
พร็อพเพอร์ตี้ color-scheme เป็นการเพิ่มประสิทธิภาพแบบต่อเนื่อง
เบราว์เซอร์ที่ไม่รองรับจะละเว้นพร็อพเพอร์ตี้นี้และใช้ UI โหมดสว่างเริ่มต้น
หากต้องการปรับให้เข้ากับค่ากำหนดของผู้ใช้ในเบราว์เซอร์รุ่นเก่า ให้ใช้คิวรี่สื่อ prefers-color-scheme เพื่อแสดงสีที่แตกต่างกันเมื่อผู้ใช้ต้องการใช้โหมดมืด
- ควรใช้การค้นหาสื่อเพื่อสลับคุณสมบัติที่กำหนดเองใน
:rootหรือhtml - หลีกเลี่ยงการใช้การค้นหาสื่อในคอมโพเนนต์แต่ละรายการ เว้นแต่คอมโพเนนต์นั้นจะต้องมีการปรับแต่งโหมดมืดที่เฉพาะเจาะจงมากนอกเหนือจากสี
:root {
/* Define brand colors for each mode */
--color-brand-light: #0056b3;
--color-brand-dark: #00e5ff;
--color-brand: var(--color-brand-light);
/* MANDATORY: Fallback for browsers without light-dark support */
@media (prefers-color-scheme: dark) {
--color-brand: var(--color-brand-dark);
}
/* Ignored in older browsers */
color-scheme: light dark;
}
button.primary {
background-color: var(--color-brand);
}
การสนับสนุนเบราว์เซอร์และทางเลือกสำรองสำหรับ light-dark()
สำหรับเบราว์เซอร์ที่รองรับ color-scheme แต่ยังไม่รองรับ light-dark() ควรกำหนดเวอร์ชันสีอ่อนและสีเข้มเป็นคุณสมบัติที่กำหนดเองก่อน และควรใช้มีเดียคิวรี prefers-color-scheme เพื่อตั้งค่าสีสำหรับโหมดที่เกี่ยวข้อง ดังตัวอย่างด้านล่าง
:root {
/* Define browser UI accent color for each mode */
--brand-accent-light: #0056b3;
--brand-accent-dark: #00e5ff;
--accent-color: var(--brand-accent-light);
/* MANDATORY: Fallback for browsers without light-dark support */
@media (prefers-color-scheme: dark) {
--accent-color: var(--brand-accent-dark);
}
/* OPTIONAL: use light-dark() for more control of built-in UI colors */
@supports (color: light-dark(white, black)) {
--accent-color: light-dark(var(--brand-accent-light), var(--brand-accent-dark));
}
/* MANDATORY: Automatically adapt native UI to user system preferences */
color-scheme: light dark;
/* Example inherited color property */
accent-color: var(--accent-color);
}
pre, code {
color-scheme: dark;
/* **Mandatory**: any inherited color properties must be set again, even if to the same design tokens */
accent-color: var(--accent-color);
}