CSS light-dark() Generator: ทำ Dark Mode อัตโนมัติโดยไม่ต้องเขียน Media Query
เรียนรู้การใช้ CSS function light-dark() สำหรับทำธีมสว่าง/มืด พร้อมสร้างคู่สีพร้อม copy ด้วย CSS Light-Dark() Generator ฟรี
Table of Contents
สมัยก่อนการทำ dark mode แปลว่าต้องเขียนสีเป็นสองเท่า — ประกาศค่าไว้ที่หนึ่งสำหรับธีมสว่าง อีกค่าหนึ่งใน @media (prefers-color-scheme: dark) แล้วถ้ามีปุ่มสลับธีมด้วย ก็ต้องเพิ่ม override ผ่าน class อีกชั้น คูณด้วยจำนวนสีใน design system ทั้งหมด stylesheet ก็กลายเป็นเขาวงกตของ rule ที่เหมือนกันเกือบทุกบรรทัด แต่ตอนนี้ CSS function light-dark() จัดการปัญหานี้ด้วยบรรทัดเดียว
หัวใจของ light-dark() คือการประกาศ "คู่สี" ทั้งสองธีมไว้ใน value เดียว แล้วให้ browser เลือกค่าที่ถูกต้องให้อัตโนมัติตาม color scheme ที่กำลังใช้งาน เครื่องมือ CSS Light-Dark() Generator ของเราให้ color picker สำหรับสีทั้งสองฝั่ง live preview เรียงคู่แบบเรียลไทม์ และ output พร้อม copy ถึง 3 แบบ — value เปล่า ๆ, rule เต็ม, และ full snippet ที่รวม color-scheme มาให้
ในบทความนี้คุณจะได้เรียนรู้ว่า function นี้ทำงานยังไงในเบื้องหลัง ต่างจากการทำธีมแบบ media query ตรงไหน และจะใช้ generator สร้างคู่สี adaptive ได้ในไม่กี่วินาทีอย่างไร
ทำไมต้องใช้ CSS Light-Dark() Generator
- ประกาศครั้งเดียว ได้สองธีม — light-dark() รวมคู่สี light/dark ไว้ใน value เดียว ตัดบล็อกซ้ำซ้อนที่การทำธีมแบบ media query ต้องเขียนทั้งหมด
- Live preview แบบเรียลไทม์ — generator เรนเดอร์การ์ด Light ☀️ และ Dark 🌙 คู่กันทันทีที่เปลี่ยนสี เห็นผลลัพธ์ทั้งสองฝั่งก่อนเอาไปใช้จริง ไม่ต้องสลับธีมไปมา
- รองรับ 10 property ตั้งแต่ในกล่อง — เลือกได้จาก color, background-color, border-color, text-decoration-color, fill, stroke, outline-color, caret-color, สีของ box-shadow หรือพิมพ์ custom property อย่าง --my-brand-color ก็ได้
- Output 3 รูปแบบพร้อม copy — จะเอาแค่ light-dark() value ไปใช้แบบ inline, rule CSS ที่สมบูรณ์ หรือ full snippet ที่แถม color-scheme: light dark; มาด้วย เลือกได้ตามสถานการณ์
- ไม่ต้องพึ่ง media query — เพราะ browser resolve คู่สีให้เอง คุณเลยเลิกดูแลบล็อก @media (prefers-color-scheme: dark) เป็นสิบ ๆ บล็อกได้เลย
- ทำงาน client-side 100% ฟรี — ทุกอย่างรันใน browser ของคุณ ไม่ต้องสมัครสมาชิก ไม่ต้อง upload อะไร สีที่คุณเลือกไม่เคยออกจากเครื่อง
ฟีเจอร์เด่น
| ฟีเจอร์ | รายละเอียด |
|---|---|
| Color picker สองฝั่ง | เลือกค่า hex สำหรับแต่ละธีม พิมพ์ค่าแบบละเอียดได้ (ค่าเริ่มต้น #ffffff / #1a1a1a) |
| Property selector | เลือก target จาก 9 property ยอดนิยม หรือระบุ custom property เอง |
| Live preview cards | เรนเดอร์ Light และ Dark คู่กันโดย apply color-scheme แยกฝั่ง พร้อมโชว์ hex code ทั้งสองค่า |
| Output พร้อม copy | ปุ่ม copy แยกสำหรับ value, rule และ full snippet |
| รวม color-scheme | full snippet แถมบรรทัด color-scheme: light dark; ให้ เพื่อให้คู่สีทำงานถูกต้องทันที |
หมายเหตุสำคัญเรื่อง property selector — เพราะ light-dark() เป็น color value (ไม่ใช่ property) มันจึงใช้ได้ทุกที่ที่รับค่าสี รวมถึง fill และ stroke ของ SVG, caret-color และ custom property ด้วย dropdown ของ generator จะสร้างรูปร่าง rule ที่ถูกต้องให้แต่ละ target คุณไม่ต้องประกอบเอง
ส่วน full snippet คือจุดเริ่มต้นที่ปลอดภัยที่สุดสำหรับโปรเจกต์จริง เพราะเติม color-scheme: light dark; มาพร้อมคู่สี ซึ่งเป็น "สวิตช์" ที่ browser ใช้ตัดสินว่าจะเรนเดอร์ฝั่งไหนของคู่ การ copy เฉพาะ value ก็ใช้ได้ แต่ต้องมั่นใจว่า color-scheme ถูกประกาศไว้แล้วที่ไหนสักแห่งใน scope นั้น
วิธีใช้งาน
- เปิด CSS Light-Dark() Generator — ไม่ต้องมี account
- เลือก สีสำหรับ light mode และ สีสำหรับ dark mode จาก color picker สองตัว หรือพิมพ์ค่า hex แบบเป๊ะ เช่น #1a1a1a
- เลือก CSS property ที่ต้องการ theme จาก dropdown — หรือเลือก custom property แล้วพิมพ์ชื่อ เช่น --brand-accent
- ดู live preview อัปเดตทันที — การ์ด Light แสดงสีแรก การ์ด Dark แสดงสีที่สอง แต่ละใบรันภายใต้ color-scheme ของตัวเอง
- กด Copy ที่ output ที่ต้องการ — ไม่ว่าจะเป็น light-dark() value, rule เดี่ยว หรือ full snippet พร้อม color-scheme: light dark; — แล้วนำไปวางใน stylesheet
เข้าใจ light-dark() และ color-scheme
function light-dark() รับ argument สองตัวเป๊ะ ๆ — สีสำหรับ light scheme และสีสำหรับ dark scheme:
.button-text {
color: light-dark(#1a1a1a, #ffffff);
}
เมื่อหน้าเว็บเรนเดอร์ด้วย light color scheme browser จะ resolve value นี้เป็น #1a1a1a แต่ถ้าเป็น dark color scheme ก็จะได้ #ffffff — ไม่มี cascade ซับซ้อน ไม่มี selector ซ้ำซ้อน การเลือกเกิดขึ้นที่ระดับ value โดยตรง
แต่ function นี้จะทำงานก็ต่อเมื่อ element อยู่ภายใต้ context ที่ประกาศรองรับทั้งสอง scheme:
:root {
color-scheme: light dark;
}
declaration นี้บอก browser ว่า "เอกสารนี้รองรับทั้ง light และ dark" และมันคือสวิตช์ที่พลิกทุก light-dark() value บนหน้าเว็บ ถ้าอยากได้ปุ่มสลับธีมแบบ manual แทนการตามค่า OS ให้เซ็ต color-scheme: light; หรือ color-scheme: dark; ที่ root ตอน runtime — ทุกคู่สีจะเปลี่ยนตามทันที เร็วและง่ายกว่าการ toggle class แล้วประกาศสีใหม่ทั้งชุดมาก
Browser support ถือว่าดีแล้วบน engine สมัยใหม่ — Chrome และ Edge 123+, Firefox 120+, และ Safari 17.5+ สำหรับ browser เก่ากว่านั้น ให้ทำ fallback ด้วย @supports:
:root {
color-scheme: light dark;
}
.text-primary {
color: #1a1a1a; /* fallback สำหรับ browser เก่า */
}
@supports (color: light-dark(#fff, #000)) {
.text-primary {
color: light-dark(#1a1a1a, #ffffff);
}
}
แล้วต่างจาก @media (prefers-color-scheme: dark) ตรงไหน? แนวทาง media query ต้องทำซ้ำทุก rule ที่เกี่ยวกับสี — ทีละชุดสำหรับค่า default และอีกชุดใน query แต่ light-dark() กลับด้านกระบวนท่า โดยให้คู่สีอยู่ใน declaration เดียว แล้วให้ color-scheme (ซึ่งควบคุมได้จาก media query, class หรือ JavaScript) เป็นคนพลิกทั้งหมดในครั้งเดียว — ได้พฤติกรรมตาม OS เหมือนเดิม แต่ CSS น้อยลงมาก แถมการสลับธีมแบบ manual กลายเป็นการแก้ property เดียว
Use cases จริง
ทำธีมให้ design system
design token เป็นคู่โดยธรรมชาติ — token ทุกตัวไม่ว่าจะเป็น "surface", "text" หรือ "border" ล้วนมีเวอร์ชัน light และ dark ประกาศตรง ๆ ได้เลย:
:root {
color-scheme: light dark;
--color-text: light-dark(#1a1a1a, #f5f5f5);
--color-surface: light-dark(#ffffff, #171a26);
--color-border: light-dark(#e5e5e5, #2e3450);
}
component ทุกตัวที่ใช้ token เหล่านี้จะกลายเป็น theme-aware โดยไม่ต้องเพิ่ม rule สักบรรทัด
คู่สีแบรนด์
สีแบรนด์มักไม่ map ตรงกันระหว่างธีม — น้ำเงินเข้มสดใสอาจต้องมีเวอร์ชันที่สว่างและจางลงบนพื้นมืดเพื่อ contrast ที่สบายตา live preview คู่ของ generator ถูกออกแบบมาเพื่องานนี้โดยเฉพาะ — หมุนค่าฝั่ง dark จนการ์ดทั้งสองใบดูสมดุล แล้ว copy คู่สีนั้นไป
ย้ายระบบ dark mode เดิม
ถ้า stylesheet ของคุณเต็มไปด้วย override ใน @media (prefers-color-scheme: dark) ให้ย้ายแบบค่อยเป็นค่อยไป — แทนที่ property ที่จับคู่กันทีละตัวด้วย value แบบ light-dark() คง media query ไว้จนกว่าคู่สีทุกคู่ในนั้นถูกแปลงหมด แล้วค่อยลบ query ที่ว่างแล้วทิ้ง output แบบ single rule ของ generator หย่อนลง workflow นี้ได้เลย
Component library
คนทำ library สามารถส่งมอบ component ที่ theme-aware ได้โดยไม่ต้องรู้กลยุทธ์การทำธีมของหน้าเว็บที่ใช้ — button ที่ style ด้วย light-dark() จะปรับตัวตาม color-scheme ที่แอปฝั่ง consumer เซ็ต ไม่ต้องมีสัญญาตัวแปร CSS ไม่ต้องเคารพ attribute อย่าง data-theme
Best Practices
- ประกาศ color-scheme: light dark; ที่ :root เสมอ (หรือ scope ที่เกี่ยวข้อง) — ถ้าไม่มีบรรทัดนี้ light-dark() จะไม่สลับ และทั้งสองธีมจะเรนเดอร์สีตัวแรกเหมือนกัน
- เช็ค contrast ทั้งสองธีม — คู่สีที่ผ่าน WCAG บนพื้นสว่างอาจไม่ผ่านบนพื้นมืด อย่าลืมเอาค่า hex ทั้งสองไปตรวจด้วย contrast checker ก่อน ship
- ใช้ full snippet ในโปรเจกต์ใหม่ เพื่อให้ color-scheme กับคู่สีถูกแนะนำพร้อมกันเสมอ
- ครอบด้วย @supports เมื่อต้องรองรับ browser เก่า โดยวาง fallback สีเดี่ยวไว้ก่อน declaration ที่ดีกว่า
- นิยมตั้งชื่อ custom property แบบ semantic — เก็บคู่สีไว้ใน token อย่าง --color-text แล้วให้ component อ้างถึง token ตรง ๆ จะได้ retheme ทั้งระบบจากจุดเดียว
- ทดสอบเส้นทาง manual toggle — ถ้ามีปุ่มสลับธีม ให้พลิก color-scheme ที่ root ผ่าน JavaScript แล้วยืนยันว่าทุกคู่สีตอบสนอง — เป็นวิธีเร็วที่สุดที่จะเจอ declaration ที่หายไป
เริ่มสร้างสี adaptive วันนี้
light-dark() คือ primitive สำหรับทำ dark mode ที่สะอาดที่สุดที่ CSS เคยออกแบบมาในรอบหลายปี และพอมี CSS Light-Dark() Generator การเปลี่ยนคู่สีของคุณให้เป็น CSS พร้อม production ใช้เวลาไม่ถึงนาที — เลือกสองสี ดูทั้งสองธีมเรนเดอร์สด ๆ copy snippet จบ
ไม่ต้องประกาศซ้ำ ไม่ต้องเจอเขาวงกต media query มีแต่คู่สีที่ปรับตัวเอง — ขอให้สนุกกับการทำธีม!
เครื่องมือที่เกี่ยวข้อง:
- Color Scheme Generator — สร้าง declaration color-scheme ครบชุด
- Color Contrast Checker — เช็ค WCAG contrast ทั้งสองธีม
- Color Blindness Simulator — จำลองการมองเห็นของผู้ใช้ที่มี color blindness