พร็อพเพอร์ตี้ color-scheme จะระบุรูปแบบสี (เช่น สว่างหรือมืด) ที่หน้ารองรับ ซึ่งจะแจ้งให้เบราว์เซอร์ทราบว่าสามารถกำหนดธีมองค์ประกอบ UI แบบเนทีฟโดยอัตโนมัติ เช่น แถบเลื่อน ตัวควบคุมแบบฟอร์ม และพื้นหลัง Canvas เริ่มต้น เพื่อให้ตรงกับการออกแบบเว็บไซต์และช่วยลดแสงแฟลชสีขาวระหว่างการโหลดครั้งแรก
การใช้งาน
1. ประกาศรูปแบบที่รองรับใน HTML
บังคับ: เพื่อช่วยป้องกัน "การแสดงเนื้อหาที่ไม่มีธีมชั่วคราว" (FOUC) ให้วางแท็ก <meta> ใน <head> เพื่อให้เบราว์เซอร์ทราบว่าคุณรองรับธีมใดก่อนที่จะเริ่มแสดงผล แม้ว่าแท็ก <meta> นี้จะช่วยหลีกเลี่ยง FOUC ได้โดยการตั้งค่าสี Canvas เริ่มต้นตั้งแต่เนิ่นๆ แต่ก็อาจไม่สามารถกำจัดการกะพริบในเบราว์เซอร์หรือเงื่อนไขการโหลดทั้งหมดได้อย่างสมบูรณ์
<!-- MANDATORY: Declare support for both light and dark themes -->
<meta name="color-scheme" content="light dark">
2. ใช้รูปแบบสีทั้งหน้ากับ CSS :root หรือ html
บังคับ: ใช้พร็อพเพอร์ตี้ color-scheme กับองค์ประกอบ html หรือคลาสเทียม :root เบราว์เซอร์จะดูองค์ประกอบรูทโดยเฉพาะเพื่อกำหนดธีมสำหรับวิวพอร์ตทั้งหมด ซึ่งรวมถึงแถบเลื่อนรูทและพื้นหลัง "Canvas" เริ่มต้น หากใช้กับ body เท่านั้น พื้นผิว UI ส่วนกลางเหล่านี้อาจยังคงอยู่ในโหมดสว่างเนื่องจาก body ไม่ได้ควบคุมบริบทการแสดงผลของหน้าต่าง
/* MANDATORY: Apply color-scheme to :root or html for viewport-wide theming */
:root {
/* MANDATORY: Automatically adapt native UI to user system preferences */
color-scheme: light dark;
}
3. กำหนดโทเค็นสีสว่างและสีมืด
คุณสามารถใช้ฟังก์ชัน light-dark() เพื่อกำหนดโทเค็นสีที่ปรับให้เข้ากับค่า color-scheme ต่างๆ โดยอัตโนมัติ
เราขอแนะนำให้คุณเก็บค่าสีดิบไว้ในคุณสมบัติที่กำหนดเองแยกต่างหาก ซึ่งจะช่วยให้รวมค่าสีในรูปแบบต่างๆ ได้ง่ายขึ้น (และทำให้ลักษณะการทำงานสำรองง่ายขึ้น หากจำเป็น)
หากต้องการควบคุมสีของ UI ในตัว เช่น accent-color หรือ scrollbar-color ได้มากขึ้น ผู้เขียนสามารถเลือกเพิ่มสีแบบไดนามิกของตนเองได้โดยใช้คุณสมบัติที่กำหนดเองและ/หรือฟังก์ชัน light-dark() ฟังก์ชันนี้จะเลือกสีที่ถูกต้องโดยอัตโนมัติตาม color-scheme ที่คำนวณแล้วขององค์ประกอบ และไม่จำเป็นต้องใช้การค้นหาสื่อที่ซ้ำซ้อน แต่ไม่จำเป็นสำหรับการติดตั้งใช้งานขั้นพื้นฐาน
:root {
--color-brand-light: oklch(45% 0.23 270);
--color-brand-dark: oklch(85% 0.15 210);
--color-brand-text-light: white;
--color-brand-text-dark: oklch(40% 0.23 270);
--color-brand: light-dark(var(--color-brand-light), var(--color-brand-dark));
--color-brand-text: light-dark(var(--color-brand-text-light), var(--color-brand-text-dark));
/* MANDATORY: Automatically adapt native UI to user system preferences */
color-scheme: light dark;
}
button.primary {
/* These automatically adapt to color scheme */
background-color: var(--color-brand);
color: var(--color-brand-text);
}
ไม่บังคับ: มีสีของระบบให้เลือกใช้จำนวนหนึ่ง ซึ่งจะปรับให้เข้ากับรูปแบบสีที่ใช้โดยอัตโนมัติ (และโหมดสีอื่นๆ เช่น สีที่บังคับ) เช่น canvas, canvastext, accentcolor (ตรวจสอบการรองรับ), buttonborder เป็นต้น โดยทั่วไปแล้ว สีเหล่านี้มีข้อจำกัดมากเกินกว่าที่จะเป็นประโยชน์ นอกเหนือจากกรณีที่เฉพาะเจาะจงมากซึ่งคุณต้องจับคู่ UI ของเบราว์เซอร์เริ่มต้นบางอย่างให้ตรงกันทุกประการ หรือใช้เป็นสีสำรอง/สีเริ่มต้น
ไม่บังคับ: ปรับแต่งคู่สีให้เหมาะกับบริบท
แม้ว่าจะลบล้างค่าเริ่มต้นของระบบ แต่การใช้คิวรี่สื่อ prefers-color-scheme เพื่อกำหนดคู่สีที่แตกต่างกันซึ่งคำนึงถึงสีของเบราว์เซอร์และ Chrome ของระบบปฏิบัติการรอบๆ หน้า (หรือของหน้าที่อยู่รอบๆ เมื่อใช้หน้าเป็น iframe) ก็อาจเป็นประโยชน์
เช่น ใช้ธีมสว่างที่มืดลงเล็กน้อยเมื่อการตั้งค่าระบบเป็น dark หรือธีมมืดที่มีคอนทราสต์มากขึ้นเมื่อการตั้งค่าระบบเป็น light เพื่อไม่ให้หน้าเว็บดูโดดเด่นกว่า UI โดยรอบมากเกินไป
การปรับแต่ง UI ของเบราว์เซอร์แบบละเอียด
การตั้งค่า color-scheme จะปรับ UI ของเบราว์เซอร์ให้เข้ากับรูปแบบสีที่ใช้แล้ว แต่จะใช้ค่าเริ่มต้นของระบบปฏิบัติการและ/หรือสีของระบบที่อาจไม่สอดคล้องกับการออกแบบเว็บไซต์อย่างสมบูรณ์
เบราว์เซอร์ที่ทันสมัยมีฮุกการปรับแต่งที่ละเอียดหลายรายการสำหรับสิ่งเหล่านี้
อย่าใช้การควบคุมแบบเนทีฟซ้ำเพียงเพื่อปรับแต่งลักษณะที่ปรากฏโดยไม่ใช้ฮุกการปรับแต่งที่เบราว์เซอร์ที่ทันสมัยมีให้จนหมด
การตั้งค่าสีเฉพาะจุด
UI ของเบราว์เซอร์บางรายการ (เช่น ช่องทำเครื่องหมายที่เลือกหรือแถบเลื่อน) จะใช้สีเฉพาะจุด
ซึ่งจะเปลี่ยนเป็นค่าเริ่มต้นของการตั้งค่าระบบปฏิบัติการ แต่คุณสามารถใช้พร็อพเพอร์ตี้ accent-color เพื่อตั้งค่าเป็นสีที่สอดคล้องกับหน้าเว็บได้ดีขึ้น เช่น สีของแบรนด์ของหน้าเว็บ
html {
accent-color: light-dark(var(--color-accent-light), var(--color-accent-dark));
}
ปัญหาที่ควรทราบเมื่อใช้ accent-color
การแสดงผล accent-color ของเบราว์เซอร์จะแตกต่างกันไป
สำหรับตัวบ่งชี้ที่มักจะวาดทับพื้นหลังสีเฉพาะจุด เช่น เครื่องหมายช่องทำเครื่องหมายและจุดปุ่มตัวเลือก เบราว์เซอร์อาจใช้การดำเนินการที่แตกต่างกัน ดังนี้
- โดยทั่วไป Chromium และ Firefox จะเลือกสีตัวบ่งชี้ที่ตัดกัน
- Safari อาจคงตัวบ่งชี้สีขาวไว้ในโหมดสว่างหรือตัวบ่งชี้สีดำในโหมดมืดแทน ขณะที่แก้ไขสีเฉพาะจุดด้านหลัง การปรับนี้ไม่ได้ให้คอนทราสต์ที่เพียงพอสำหรับทุกสีที่ระบุเสมอไป ดังนั้นให้ทดสอบชุดค่าผสมที่สำคัญใน Safari ซึ่งรวมถึงรูปแบบสีทั้งสว่างและมืด อย่าคิดว่า Safari จะเลือกสีตัวบ่งชี้ที่ให้คอนทราสต์ที่ดีที่สุดโดยอัตโนมัติ
สีของแถบเลื่อน
คุณสามารถใช้ scrollbar-color ร่วมกับ light-dark() เพื่อตั้งค่าสีแถบเลื่อนที่กำหนดเองซึ่งปรับให้เข้ากับรูปแบบสีที่ใช้ได้
:root {
--color-scrollbar-track: light-dark(#eee, #222);
--color-scrollbar-thumb: light-dark(#999, #666);
scrollbar-color: var(--color-scrollbar-thumb) var(--color-scrollbar-track);
}
ปัญหาที่ควรทราบเมื่อใช้ scrollbar-color
- ห้ามใส่ภาพเคลื่อนไหวหรือการเปลี่ยนภาพให้กับ
scrollbar-colorข้อบกพร่องของ WebKit ทำให้แถบเลื่อนกะพริบทุกครั้งที่scrollbar-colorมีการเปลี่ยนแปลง - ใน macOS ระบบจะละเว้นพร็อพเพอร์ตี้
scrollbar-color(มาตรฐาน) และ::-webkit-scrollbar(เดิม) โดยค่าเริ่มต้น เนื่องจาก macOS ใช้แถบเลื่อน "วางซ้อน" แบบเนทีฟ คุณต้องจับคู่สีแบบกำหนดเองกับscrollbar-width(เช่นthinหรือauto) เพื่อบังคับให้ macOS แสดงผลสีเหล่านั้น - แม้ว่าจะใช้
scrollbar-widthแล้ว แต่แถบเลื่อนแบบวางซ้อนของ macOS จะแสดงผลแทร็ก (ราง) เป็นแบบโปร่งใสโดยค่าเริ่มต้น หากการออกแบบกำหนดให้ต้องมีสีพื้นหลังของแทร็กที่มองเห็นได้ใน MacOS คุณต้องใช้scrollbar-gutter: stable;กับคอนเทนเนอร์ที่เลื่อนได้ แต่โปรดทราบว่าสีพื้นหลังจะปรากฏหลังจากที่ผู้ใช้วางเมาส์เหนือแถบเลื่อนเท่านั้น - แม้จะใช้
scrollbar-gutter: stableแทร็กก็อาจโปร่งใสใน MacOS Thumb ไม่ควรขึ้นอยู่กับสีของแทร็กเพื่อให้มองเห็นได้
การปรับแต่งเพิ่มเติม
UI ของเบราว์เซอร์ส่วนใหญ่จะแสดงองค์ประกอบจำลองเพื่อปรับแต่งลักษณะที่ปรากฏได้อย่างเต็มที่ เช่น
::placeholder::spelling-error::grammar-error::selection::search-text::target-text::file-selector-button
คุณสามารถใช้สี light-dark() กับองค์ประกอบเหล่านี้เพื่อใช้สีที่ปรับให้เข้ากับรูปแบบสีที่ใช้
4. รูปภาพที่แตกต่างกันสำหรับโหมดสว่างและโหมดมืด
สำหรับรูปภาพ CSS คุณยังใช้ light-dark() เพื่อระบุค่ารูปภาพที่แตกต่างกันได้ด้วย
สำคัญ: ค่าทั้ง 2 ค่าใน light-dark() ต้องเป็นประเภทเดียวกัน คุณไม่สามารถรวมสีเข้ากับรูปภาพได้
หากค่าใดค่าหนึ่งต้องเป็นรูปภาพ ให้ใช้ image(<color>) เพื่อรวมค่าสี
การตรวจจับธีมที่ใช้ JS
การแยกรูปแบบสีส่วนใหญ่ควรทำใน CSS ซึ่งจะปรับให้เข้ากับการเปลี่ยนแปลงโดยอัตโนมัติ
การอ่าน JS matchMedia("(prefers-color-scheme: dark)").matches จะต้องจัดการเหตุการณ์ change ด้วย เนื่องจากค่ากำหนดของระบบอาจเปลี่ยนแปลงได้ทุกเมื่อ
ไม่บังคับ: การใช้ปุ่มสลับรูปแบบสี
หากต้องการอนุญาตให้ผู้ใช้ลบล้างค่าเริ่มต้นของระบบสำหรับเว็บไซต์นี้ด้วยตนเอง คุณสามารถใช้ปุ่มเปิด/ปิดโหมดมืดได้ เว็บไซต์ส่วนใหญ่ไม่จำเป็นต้องมีปุ่มเปิด/ปิดแบบถาวรใน UI ของเว็บไซต์ โดยปกติแล้ว การใช้รูปแบบสีของระบบเป็นค่าเริ่มต้นก็เพียงพอแล้ว โดยอาจมีตัวเลือกการตั้งค่าในแพลตฟอร์มการตั้งค่าแยกต่างหาก ดูปุ่มเปิด/ปิดโหมดมืดเพื่อดูแนวทางปฏิบัติแนะนำเกี่ยวกับการใช้ปุ่มเปิด/ปิดโหมดมืด (ถาวรหรือไม่)
ไม่บังคับ: การลบล้างเฉพาะคอมโพเนนต์
คุณสามารถลบล้างธีมส่วนกลางสำหรับองค์ประกอบที่เฉพาะเจาะจงได้โดยตั้งค่า color-scheme ในองค์ประกอบเหล่านั้น
ดูข้อมูลเพิ่มเติมและข้อควรระวังได้ที่ธีมสว่าง/มืดเฉพาะคอมโพเนนต์
ปัญหาที่ทราบซึ่งควรคำนึงถึง
ปัญหาที่ควรทราบเมื่อใช้รูปแบบสี
- 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);
}
การรองรับเบราว์เซอร์และทางเลือกสำรองสำหรับค่ารูปภาพ light-dark()
สำหรับเบราว์เซอร์ที่ไม่รองรับ light-dark() สำหรับรูปภาพ ให้ใช้ image-set() เป็นสวิตช์ โดยกำหนด type() ให้กับแต่ละตัวเลือกจากคุณสมบัติที่กำหนดเอง และตั้งค่าตัวเลือกที่ไม่ได้ใช้งานเป็นประเภท MIME ที่ไม่รองรับเพื่อให้เบราว์เซอร์ทิ้งตัวเลือกนั้น
ตัวเลือกที่ใช้งานอยู่จะได้รับค่าว่าง ดังนั้นจึงเป็นตัวเลือก image-set() ธรรมดาที่ไม่มี type()
กำหนดสวิตช์ 1 ครั้งใน :root จากนั้นเว็บไซต์ที่ใช้ทุกแห่งจะต้องมีรูปภาพทั้ง 2 รูปในบรรทัด เช่น light-dark()
:root {
--light-type: ;
--dark-type: type("image/do-not-use");
/* MANDATORY: Fallback for browsers without light-dark() image support */
@media (prefers-color-scheme: dark) {
--light-type: type("image/do-not-use");
--dark-type: ;
}
}
.hero {
background-image: image-set(url(hero-light.png) var(--light-type), url(hero-dark.png) var(--dark-type));
@supports (background-image: light-dark(url("a"), url("b"))) {
background-image: light-dark(url(hero-light.png), url(hero-dark.png));
}
}
- ระบบจะดาวน์โหลดเฉพาะรูปภาพที่เลือกเท่านั้น
- ความละเอียดที่ยังใช้งานได้:
image-set(url(a-1x.png) 1x var(--light-type), url(a-2x.png) 2x var(--light-type), url(b-1x.png) 1x var(--dark-type), url(b-2x.png) 2x var(--dark-type)) - อย่าใช้
type("")สำหรับตัวเลือกที่ใช้งานอยู่ เบราว์เซอร์จะถือว่าสตริงว่างไม่รองรับและทิ้งทุกตัวเลือก - สวิตช์จะไม่เป็นไปตาม
color-schemeที่ตั้งค่าไว้ในโครงสร้างย่อย ซึ่งต่างจากlight-dark()การสลับด้วยตนเองหรือโครงสร้างย่อยที่ตั้งค่าcolor-schemeต้องสลับ--light-typeและ--dark-typeด้วย
ทางเลือก: คุณสมบัติที่กำหนดเอง 1 รายการต่อรูปภาพ
วิธีนี้จะง่ายกว่าเมื่อมีรูปภาพที่แตกต่างกันเพียงไม่กี่รูป แต่รูปภาพทุกรูปต้องมีสาขา Media Query ของตัวเอง และต้องสลับแต่ละรูปด้วยตนเอง
:root {
--hero-image: url(hero-light.png);
@media (prefers-color-scheme: dark) {
--hero-image: url(hero-dark.png);
}
@supports (background-image: light-dark(url("a"), url("b"))) {
--hero-image: light-dark(url(hero-light.png), url(hero-dark.png));
}
}
.hero {
background-image: var(--hero-image);
}
การสนับสนุนเบราว์เซอร์และทางเลือกสำรองสำหรับ image()
ใช้การไล่ระดับสีที่มีจุดสีเดียวและไม่มีตำแหน่ง เช่น linear-gradient(blue)
หากต้องการให้เบราว์เซอร์รองรับได้กว้างขึ้น คุณสามารถระบุตำแหน่ง 0 100% สำหรับจุดสีเดียวอย่างชัดเจน เช่น linear-gradient(blue 0 100%)
การรองรับเบราว์เซอร์และทางเลือกสำหรับ scrollbar-color
ฟีเจอร์นี้เป็นการเพิ่มประสิทธิภาพแบบต่อเนื่องและไม่จำเป็นต้องใช้กลยุทธ์สำรองเสมอไป
หากการจัดรูปแบบมีความสำคัญและเป้าหมาย Baseline ของผู้ใช้คือ "Baseline ที่พร้อมใช้งานในวงกว้าง" หรือเก่ากว่า คุณควรใส่องค์ประกอบเทียม ::-webkit-scrollbar ที่ไม่ใช่มาตรฐานเป็นทางเลือกสำรอง
รวมการใช้ CSS แบบเดิมไว้ในบล็อก @supports not (scrollbar-color: auto) เพื่อป้องกันความขัดแย้งระหว่างพร็อพเพอร์ตี้มาตรฐานกับตัวเลือก WebKit แบบเดิมในเบราว์เซอร์ที่รองรับทั้ง 2 แบบโดยค่าเริ่มต้น
หากคุณใช้คุณสมบัติที่กำหนดเองเพื่อกำหนดสี คุณสมบัติเหล่านี้จะเรียงซ้อนไปยังตัวเลือก WebKit เดิมโดยอัตโนมัติ คุณไม่จำเป็นต้องทำซ้ำ
/* Legacy fallback for WebKit/Blink browsers */
@supports not (scrollbar-color: auto) {
.scroller::-webkit-scrollbar {
/* Must define base size in WebKit for custom colors to be visual */
width: 12px;
height: 12px;
}
.scroller::-webkit-scrollbar-thumb {
background: var(--scrollbar-thumb);
}
.scroller::-webkit-scrollbar-track {
background: var(--scrollbar-track);
}
}
การสำรองและการรองรับเบราว์เซอร์สำหรับ accent-color
พร็อพเพอร์ตี้ accent-color เป็นการเพิ่มประสิทธิภาพแบบต่อเนื่อง
เบราว์เซอร์ที่ไม่รองรับพร็อพเพอร์ตี้นี้จะละเว้นและใช้สี UI เริ่มต้น