- ฟังก์ชัน contrast-color() ช่วยให้เบราว์เซอร์เลือก สีตัวอักษรเป็นสีดำหรือสีขาว ให้อัตโนมัติตามสีพื้นหลังที่หลากหลาย เช่น ปุ่ม
- แม้ในโปรเจ็กต์ขนาดใหญ่ก็ช่วยให้ รักษาความอ่านง่ายของข้อความ ได้ง่ายขึ้น และเพิ่มประสิทธิภาพในการดูแลรักษา
- ปัจจุบันใน Safari Technology Preview ใช้อัลกอริทึมทางการของ WCAG 2 ซึ่งอาจไม่สอดคล้องกับการรับรู้ของมนุษย์จริง
- กำลังมีการหารือเรื่องการนำอัลกอริทึม APCA รุ่นถัดไปมาใช้ในกระบวนการพัฒนา WCAG 3 และคาดว่าจะช่วยให้ การประเมินคอนทราสต์ด้านความสว่าง ดีขึ้น
- นอกเหนือจากคอนทราสต์ขาวดำแบบง่าย ๆ แล้ว ในอนาคตยังมีแนวโน้มจะเพิ่มตัวเลือกสีที่หลากหลายและฟีเจอร์ ปรับปรุงการเข้าถึง เพิ่มเติม
ภาพรวมและที่มาของการนำ contrast-color() มาใช้
- ในงานออกแบบที่มีการใช้สีพื้นหลังหลากหลายกับปุ่มหรือองค์ประกอบอินเทอร์เฟซต่าง ๆ สีตัวอักษร (text color) ที่อ่านง่ายถือว่าสำคัญมาก
- ก่อนหน้านี้นักพัฒนาต้องจับคู่สีพื้นหลังกับสีข้อความด้วยตัวเองทีละจุด แต่ในโปรเจ็กต์ขนาดใหญ่จะมี ความซับซ้อนในการจัดการและความเสี่ยงต่อความผิดพลาด สูง
- เมื่อใช้ ฟังก์ชัน CSS contrast-color() นักพัฒนาเพียงกำหนดสีพื้นหลัง แล้วเบราว์เซอร์จะเลือกสีตัวอักษรระหว่างสีดำหรือสีขาวที่มีคอนทราสต์สูงกว่าให้อัตโนมัติ
- วิธีนี้ช่วยเพิ่ม ประสิทธิภาพของงานดูแลรักษาและงานออกแบบ ได้อย่างมาก
- สามารถประกาศใช้งานแบบง่าย ๆ เช่น
color: contrast-color(สี);
ตัวอย่างการใช้งาน contrast-color()
- กำหนดสีที่ต้องการให้กับตัวแปรสีพื้นหลังของปุ่ม แล้วให้
contrast-color() เลือกสีข้อความขาวหรือดำที่ตัดกันโดยอัตโนมัติ
- เพราะต้องดูแลเพียงสีเดียวในแต่ละครั้ง จึงทำให้การเปลี่ยนนโยบายดีไซน์หรือการรองรับโหมดมืด/สว่างทำ maintenance ได้ง่าย
button {
background-color: var(--button-color);
color: contrast-color(var(--button-color));
}
- หากใช้ Relative Color Syntax ก็จะจัดการสีพื้นหลังและสีข้อความของสถานะ hover ให้สอดคล้องกันได้เช่นกัน
ประเด็นด้านการเข้าถึงและคำอธิบายอัลกอริทึม
- การใช้
contrast-color() ไม่ได้แก้ทุกปัญหาเรื่อง การเข้าถึง (Accessibility) ได้โดยอัตโนมัติ
- สำหรับสีพื้นหลังที่มีความสว่างระดับกลางบางสี อาจเกิดกรณีที่ทั้งสีดำและสีขาวไม่ผ่านเกณฑ์ที่ต้องการ
- ปัจจุบัน อัลกอริทึม WCAG 2 ที่ใช้ใน Safari Technology Preview เป็นมาตรฐานทางการด้านการเข้าถึงเว็บ
- อัลกอริทึมนี้เลือกโดยอิงจากอัตราส่วนคอนทราสต์ แต่บางครั้งผลลัพธ์อาจไม่ตรงกับคอนทราสต์ด้านความสว่างที่ตามนุษย์มองเห็นจริง
- ตัวอย่างเช่น บนพื้นหลังสีน้ำเงิน #317CFF ระบบคำนวณอาจตัดสินว่าสีดำมีคอนทราสต์สูงกว่า แต่ในความเป็นจริงสีขาวกลับอ่านได้ดีกว่า
- จากคำวิจารณ์และความต้องการให้ปรับปรุง จึงมีการหารือเพื่อนำ APCA (Accessible Perceptual Contrast Algorithm) ซึ่งดีกว่าเดิม มาใช้ใน มาตรฐานการเข้าถึงยุคถัดไป (WCAG 3)
- APCA คำนวณคอนทราสต์ของสีโดยสะท้อน ลักษณะการรับรู้ของมนุษย์ จึงช่วยรับประกันความอ่านง่ายในโลกจริงได้ดีกว่า
การให้คอนทราสต์ที่เพียงพอในสภาพแวดล้อมจริง
- สามารถใช้ media query ของ CSS อย่าง
@media (prefers-contrast: more) เพื่อใช้สไตล์คอนทราสต์สูงเพิ่มเติมตาม ความต้องการด้านการเข้าถึงของผู้ใช้
@media (prefers-contrast: more) {
/* กำหนดสไตล์ที่มีคอนทราสต์สูงขึ้น */
}
- ตัวอย่างเช่น หากสีหลักของแบรนด์เป็นสีเขียวสว่างอย่าง #2DAD4E แม้ในอนาคต
contrast-color() จะเลือกสีขาว ก็อาจยังมีคอนทราสต์ไม่เพียงพอสำหรับข้อความขนาดเล็ก
- เมื่อใช้อัลกอริทึม APCA จะสามารถอ้างอิงเกณฑ์คอนทราสต์ขั้นต่ำที่ต้องการได้อย่างละเอียดตามขนาดและความหนาของฟอนต์ ช่วยในการตัดสินใจด้านดีไซน์ในการทำงานจริง
- ตัวอย่างเช่น ข้อความขนาด 24px/น้ำหนัก 400 เหมาะกับการใช้สีขาว แต่ถ้าเป็น FONT ที่บางกว่านี้หรือข้อความขนาดเล็กกว่า ก็ควรใช้สีพื้นหลังที่เข้มขึ้น
- ทีมออกแบบสามารถจัดการพาเลตสีด้วยตัวแปรให้เหมาะกับแต่ละเงื่อนไขได้ง่าย โดยคำนึงถึง light/dark mode และค่ากำหนด prefers-contrast เป็นต้น
--button-color: #2DAD4E;
@media (prefers-contrast: more) {
@media (prefers-color-scheme: light) {
--button-color: #419543;
}
@media (prefers-color-scheme: dark) {
--button-color: #77CA8B;
}
}
button {
background-color: var(--button-color);
color: contrast-color(var(--button-color));
font-size: 1.5rem;
font-weight: 500;
}
- แก่นสำคัญคือด้วย
contrast-color() เราจะจัดการเพียงสีโดยยึดสีพื้นหลังเป็นศูนย์กลาง ส่วนคู่สีข้อความที่มีคอนทราสต์เหมาะสม เบราว์เซอร์จะสร้างให้โดยอัตโนมัติ
ก้าวข้ามสีดำและสีขาว
- ปัจจุบัน
contrast-color() ยังเลือกได้เพียง 2 แบบคือขาวหรือดำ แต่ในเวอร์ชันแรกเริ่มนั้นเคยมีแนวคิดให้เลือกจากหลายสีได้
- CSS Working Group ต้องการรองรับการเปลี่ยนอัลกอริทึมในอนาคตและความเข้ากันได้ จึงเริ่มจากเวอร์ชันเรียบง่ายก่อนคือเลือกเฉพาะขาว/ดำ และมีแผนจะขยายในอนาคต เช่น ตัวเลือกสีกำหนดเอง และการระบุเกณฑ์คอนทราสต์ขั้นต่ำที่ต้องการ
- สำหรับความต้องการทั่วไป ฟังก์ชันนี้ก็มีประโยชน์มากอยู่แล้ว
- ฟังก์ชันนี้สามารถประยุกต์ใช้ได้หลากหลาย ไม่ใช่แค่กับ สีพื้นหลัง แต่ยังรวมถึงเส้นขอบและองค์ประกอบด้านภาพอื่น ๆ ด้วย
บทสรุปและข้อมูลอ้างอิง
- เมื่อมาตรฐานการเข้าถึงยุคถัดไปถูกนำมาใช้
contrast-color() ก็จะเปลี่ยนอัลกอริทึมเพื่อรองรับการเลือกคอนทราสต์อัตโนมัติที่ดียิ่งขึ้น
- จนกว่าจะถึงตอนนั้น ฟังก์ชันนี้จะมีประโยชน์เป็นพิเศษเมื่อสีพื้นหลังหลักมีความสว่างหรือความมืดชัดเจน
- สามารถนำไปใช้ได้กว้างกับองค์ประกอบ UI หลากหลาย ไม่ได้จำกัดเฉพาะข้อความ
- ควรติดตามอัลกอริทึมด้านการเข้าถึงสมัยใหม่อย่าง APCA (Accessible Perceptual Contrast Algorithm) ต่อไป
เอกสารอ้างอิง
- สามารถดูตัวอย่างและเกณฑ์การประเมินเพิ่มเติมได้จากเอกสารทางการของ APCA และ APCA Contrast Calculator
- กำลังมีการหารือเรื่องมาตรฐานของ ฟังก์ชัน contrast-color ของ CSSWG
- สามารถร่วมแบ่งปันความคิดเห็นและส่งฟีดแบ็กได้ผ่าน WebKit หรือคอมมูนิตี้ที่เกี่ยวข้อง
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
ฉันกำลังพัฒนาเครื่องมือสำหรับสร้างพาเลตสีเพื่อแก้ปัญหานี้ โดยให้คู่สีมีอัตราส่วนคอนทราสต์ WCAG/ACPA ที่เรียบง่ายและคาดเดาได้ตั้งแต่ขั้นตอนออกแบบ ดูฟีเจอร์เพิ่มเติมบนเดสก์ท็อปได้ที่ https://www.inclusivecolors.com/ วิธีหนึ่งคือสร้างสวอตช์สีเป็นระดับตั้งแต่ 100 (สีอ่อน) ถึง 900 (สีเข้ม) แล้วปรับความสว่างให้เช่น สีระดับ 700 ตัดกับระดับ 100 ได้ชัดเจน และระดับ 800 ตัดกับระดับ 200 ได้ชัดเจน แบบนี้ก็จะรู้ได้ว่าอย่าง red-700 vs gray-100 หรือ green-800 vs yellow-200 ให้คอนทราสต์ที่ชัดเจนแน่นอนโดยไม่ต้องเช็กค่าความสว่าง ในเมนู Contrast ยังสามารถสำรวจได้ด้วยว่าอัลกอริทึม APCA เข้มงวดกว่า WCAG แค่ไหน โดยเฉพาะกับข้อความสีเข้มบนพื้นหลังสว่างด้วย นี่จึงเป็นเหตุผลว่าทำไมไม่ควรใช้ WCAG กับธีมมืด ในเมนู Examples ถ้าดูตัวอย่างพาเลตของ Tailwind และ IBM Carbon จะเห็นว่าแต่ละระดับมีการเปลี่ยน saturation และ hue แบบไม่เชิงเส้น ดังนั้นแม้การเลือกสีที่ตัดกันที่สุดระหว่างดำกับขาวจะทำได้ง่าย แต่พาเลตที่แบรนด์มีความสำคัญนั้นเป็นปัญหาที่ซับซ้อนกว่า ไม่ใช่แค่ปรับความสว่างอย่างเดียวก็พอ
มีวิธีทำอะไรคล้ายกันด้วย
lchที่มา: https://til.jakelazaroff.com/css/…
LCH ก็ดีมาก แต่ OKLCH ดีกว่าอีก https://evilmartians.com/chronicles/oklch-in-css-why-quit-rgb-hsl/… บทความนี้เปลี่ยนวิธีคิดของฉันไปเลย เป็นเครื่องมือที่ยอดเยี่ยมมาก น่าแปลกที่เพื่อนนักออกแบบของฉันหลายคนไม่รู้จัก OKLCH วิธีนี้แก้ปัญหาได้เยอะมาก
นี่เป็นครั้งแรกที่ฉันเห็นฟังก์ชัน CSS ที่รับพารามิเตอร์ด้วย callback แบบนี้ น่าสนใจมาก อยากรู้ว่ามีนอกจาก
lchแล้ว ยังมีฟังก์ชันสไตล์นี้อีกไหมLea Verou มีบทความดี ๆ เกี่ยวกับวิธีเลี่ยงแบบคล้ายกันนี้อยู่ https://lea.verou.me/blog/2024/contrast-color/
บทความนี้สรุปข้อดีข้อเสียของการเลือกคอนทราสต์อัตโนมัติได้ยอดเยี่ยมมาก ถ้าคุณกำลังทำเว็บง่าย ๆ วิธีนี้ให้คอนทราสต์ที่ถูกต้องได้แบบง่ายและตรงไปตรงมา
แต่ถ้าต้องรองรับ WCAG compliance ในระบบขนาดใหญ่ ควรหลีกเลี่ยง และควรมี semantic formatting token hierarchy ที่แท้จริงแทน semantic token ช่วยให้พัฒนาได้เร็วขึ้น และยังทำให้คอนทราสต์ดูสวยงามกว่าการสลับแค่ดำ/ขาว จุดดีของชั้น semantic token คือทำธีมได้ง่ายมาก ทำให้มี light/dark theme ได้แทบไม่เพิ่มต้นทุนเลย ถ้าสีแบรนด์ติดข้อจำกัดของ WCAG2 ก็สามารถทำธีมแยกสำหรับ WCAG2/APCA เพื่อให้ผ่าน compliance และยังให้คอนทราสต์ที่ดีกว่าได้
ฉันดูแลส่วน variables/tokens stream ใน Figma และเคยมีส่วนร่วมกับการทำ dark mode ของทั้ง Figma และ Atlassian ถ้ามีคำถามเรื่อง token, theme หรือสีเพื่อการเข้าถึง ถามมาได้เลย
อยากรู้ว่า semantic token หมายถึงอะไรอย่างเป็นรูปธรรม โปรเจกต์ใหญ่ที่ฉันทำเคยต้องใช้ CSS-in-JS เพื่อคำนวณสีแบบ relative และสีคอนทราสต์เพราะมีความต้องการแบบนี้ หวังว่าเทคนิคพวกนี้จะถูกนำไปใช้แพร่หลายเร็ว ๆ นี้
เนื้อหาช่วงท้าย 2/3 ดูเยิ่นเย้อเกินไปจนออกแนวอวดภูมิ สำหรับเว็บ/แอปบริษัท การพึ่งฟังก์ชันแบบนี้เสี่ยงเพราะผลลัพธ์สีคาดเดาไม่ได้ เช่น WebKit แก้บั๊กแล้วสีที่ได้อาจเปลี่ยนไป
ฉันยังรู้สึกว่ายอมรับได้ยากว่าการให้เบราว์เซอร์ตัดสินสีคอนทราสต์จะถูกต้องเสมอหรือคาดเดาได้เสมอ อยากรู้ว่าจะมีเกณฑ์ที่แน่นอนจนทุกเบราว์เซอร์ให้ผลเหมือนกันไหม ฟังก์ชันนี้ดูเหมือนเครื่องมือสนับสนุนทีม UX ในขั้นตอนออกแบบมากกว่า
ตามบทความ เขาบอกว่ามาตรฐานระบุวิธีคำนวณไว้อย่างชัดเจน
คำว่า 'เลือก' (
choose) ฟังดูคลุมเครือ จริง ๆ แล้วมันคืออัลกอริทึมที่คำนวณสีออกมาถ้าตัดส่วนที่ผิดหรือชวนสับสนออกจากสูตรตัวอย่าง APCA ในลิงก์ มันทำงานได้ถูกต้อง 100% ถ้าอยากให้สอดคล้องกันอย่างสมบูรณ์ เวลาที่สีตัวเลือกทั้งสองฝั่ง (ทั้งสว่างกว่าและมืดกว่า) ใช้ได้พร้อมกัน ก็อาจยึดความสว่าง L* ของพื้นหลังเป็นเกณฑ์ เช่น ถ้า L* ตั้งแต่ 60 ขึ้นไปก็เลือกฝั่งสว่าง แบบนี้จะสม่ำเสมอ 100%
ในโปรเจกต์ใหญ่ การคอยระวังไม่ให้ปุ่มกลายเป็นสีที่มองไม่เห็น เช่น พื้นหลังมืดแต่ตัวอักษรดำ นั้นลำบากก็จริง แต่ฉันก็อดคิดไม่ได้ว่าก่อนปล่อยจริงจะตรวจปุ่มทั้งหมดทีละจุดไม่ได้หรือ หรือจะกำหนดกติกาให้ทั้งทีมเลยว่าปุ่มพื้นเข้มห้ามใช้ข้อความสีดำเด็ดขาดก็น่าจะได้ ความแตกต่างระหว่างคอนทราสต์เชิงการรับรู้กับคอนทราสต์เชิงคณิตศาสตร์น่าสนใจมาก ฉันจะเอาไปใช้ใน workflow
ในทางปฏิบัติ การตรวจปุ่มทั้งหมดทำได้ แต่ถ้าทำแบบนั้นช่วง regression test ก่อนปล่อยอาจกินเวลาหลายสัปดาห์ หรือหนักสุดเป็นเดือน ๆ ถ้าเป็นโปรเจกต์ใหญ่ ปุ่มอาจมีเป็นพัน และหลายปุ่มจะโผล่เฉพาะในบางชุดตัวเลือกหรือบาง workflow เท่านั้น
ถ้าอ้างอิง APCA ก็จะคำนวณคอนทราสต์โดยอิงการรับรู้ได้
ฉันเคยทำสไตล์ปุ่มสมัยที่ system colors กำลังนิยม ตอนนั้นมันดูดีมาก แต่ไม่รู้ว่าคอนทราสต์จะเป็นอย่างไร เลยมีคนช่วยคำนวณด้วย JavaScript ผ่าน
getComputedStyleถ้าคอนทราสต์ไม่ผ่านก็ใช้สีตัวเลือกที่สอง หรือถ้าเลี่ยงไม่ได้ก็เพิ่มtext-shadowเพื่อเสริมความต่างรอบตัวอักษร ฉันจำวิธีคำนวณไม่ได้แล้ว แต่รู้สึกว่าแค่เอาค่า RGB ทั้ง 3 มาหาค่าเฉลี่ยแล้วเทียบก็น่าจะพอได้ อย่างน้อยกับสีน้ำเงินค่าเฉลี่ยจะต่ำ ก็อาจให้ตัวอักษรสีขาวมีความสำคัญมากกว่าอย่างน้อยก็น่าจะมีคำแนะนำสีที่เหมาะกับ pseudo-class อย่าง
active,focus,hover,link,visitedแยกตาม light/dark theme ให้ด้วย ส่วน material UI ไปไกลกว่านั้นโดยมีสถานะdisabled,before,afterเพิ่มอีกเมื่อก่อนฉันเคยทำวิดีโอสอนเรื่องการเลือกข้อความสีดำ/ขาวตามสีพื้นหลัง วิธีของฉันเรียบง่ายมาก คือแปลงสีให้เป็น grayscale แล้วค่อยตัดสินว่าจะใช้ดำหรือขาว เป็นงานที่สนุกดี แต่ทักษะทำวิดีโอยังไม่ค่อยดี
https://youtu.be/tUJvE4xfTgo?si=vFlegFA_7lzijfSR (ระวังว่าเป็นภาษาโปรตุเกส)
https://news.ycombinator.com/item?id=44015990
วิดีโอก็ดูโอเคนะ โค้ดก็ดูดี แต่ฉันไม่รู้ภาษาโปรตุเกสเลยประเมินเนื้อหาไม่ได้
ถ้าคุณเป็นคนเลือกชุดสีทั้งหมดเอง ฉันสงสัยว่าทำไมการให้ระบบช่วยเลือกสีข้อความบนปุ่มให้ตัดกัน ถึงจะง่ายกว่าการเลือกมันเองตั้งแต่ต้น ฟีเจอร์นี้ดูจะมีประโยชน์เฉพาะในสถานการณ์สุดโต่งมาก ๆ ที่พื้นหลังถูกเลือกแบบสะเปะสะปะตามใจ แต่กลับเลือกสี foreground (สีข้อความบนปุ่ม) เองไม่ได้ ทั้งที่ปัญหาจริงคือกรณีอย่างข้อความบนภาพหรือบนพื้นหลังหลากหลายรูปแบบที่ต้องอ่านได้เสมอ ซึ่งฟีเจอร์นี้ช่วยอะไรไม่ได้เลย ดังนั้นมันจึงดูเป็นฟีเจอร์ที่มีประโยชน์ได้แค่ในกรณีจำกัดมาก แถมยังถึงขั้นสร้างคำกริยาใหม่ขึ้นมา ทั้งที่ความสามารถก็แค่เลือกระหว่างขาวกับดำ และยังใช้อัลกอริทึมคอนทราสต์ที่แย่ที่สุดอย่าง WCAG 2 อีก สุดยอดจริง ๆ
น่าเสียดายที่มองข้ามเครื่องมือเพียงเพราะยังไม่เคยเจอสถานการณ์ที่ต้องใช้ มีเว็บจำนวนมากที่เปิดให้ผู้ใช้เลือกสีเองตามใจ หรือดึงสีมาจากสิ่งที่อัปโหลด เว็บที่ใส่ใจ accessibility จึงต้องมีการคำนวณคอนทราสต์อัตโนมัติสำหรับกรณีแบบนี้ การมีฟีเจอร์ใน CSS แบบ built-in จะช่วยให้รองรับ accessibility พื้นฐานได้ง่ายขึ้น แน่นอนว่ามันไม่ได้จำกัดนักพัฒนาที่อยากสร้างประสบการณ์ที่ซับซ้อนกว่านี้เลย ถ้าปรับแต่งได้มากขึ้นแบบแพ็กเกจ
contrast-colorบน npm ก็คงดี แต่ในบล็อกก็อธิบายไว้ว่าการเลือกแค่ขาว/ดำเป็นเพียงก้าวแรก และมีแผนจะพัฒนาต่อในอนาคตตัวอย่าง: https://coolors.co/8fbfe0-7c77b9-1d8a99-0bc9cd-14fff7
สำหรับข้อวิจารณ์ว่าอัลกอริทึมเลือกคอนทราสต์ไม่ดี เขาระบุชัดว่าตอนนี้ใช้ตามอัลกอริทึม WCAG 2 และเมื่อ WCAG 3 กลายเป็นมาตรฐาน ก็สามารถเปลี่ยนไปใช้อัลกอริทึมนั้นได้ไม่ยาก
สงสัยว่ามีทางเลือกแบบ build-time สำหรับฟีเจอร์ลักษณะนี้ที่ใช้กับ SASS, Tailwind ฯลฯ ได้ไหม กว่าฟีเจอร์นี้จะถูกใช้อย่างแพร่หลายคงต้องใช้เวลา และก็ยังกังวลด้วยว่าแต่ละแพลตฟอร์มจะทำออกมาเหมือนกันหรือไม่