ปรับปรุงการจัดรูปแบบเริ่มต้นของโหมดมืดด้วยพร็อพเพอร์ตี้ CSS สำหรับรูปแบบสีและเมตาแท็กที่เกี่ยวข้อง

พร็อพเพอร์ตี้ CSS color-scheme และเมตาแท็กที่เกี่ยวข้องช่วยให้นักพัฒนาแอปเลือกให้หน้าเว็บใช้สไตล์ชีต User Agent เริ่มต้นเฉพาะธีมได้

ฟีเจอร์สื่อตามค่ากำหนดของผู้ใช้ prefers-color-scheme ช่วยให้นักพัฒนาซอฟต์แวร์ควบคุมลักษณะที่ปรากฏของหน้าได้โดยสมบูรณ์ หากยังไม่คุ้นเคยกับโหมดนี้ โปรดอ่านบทความprefers-color-scheme: สวัสดี ความมืด เพื่อนเก่า ซึ่งเราได้บันทึกทุกอย่างที่รู้เกี่ยวกับการสร้างประสบการณ์การใช้งานโหมดมืดที่ยอดเยี่ยม

จิ๊กซอว์ชิ้นหนึ่งที่มีการพูดถึงแค่สั้นๆ ในบทความคือพร็อพเพอร์ตี้ CSS color-scheme และเมตาแท็กที่สอดคล้องกันที่มีชื่อเดียวกัน ทั้งสองวิธีช่วยให้ชีวิตของคุณในฐานะนักพัฒนาซอฟต์แวร์ง่ายขึ้นด้วยการให้คุณเลือกใช้หน้าเว็บในสไตล์ชีต User Agent เริ่มต้นเฉพาะธีม เช่น ตัวควบคุมแบบฟอร์ม แถบเลื่อน และสีของระบบ CSS ในขณะเดียวกัน ฟีเจอร์นี้ก็ป้องกันไม่ให้เบราว์เซอร์ใช้การเปลี่ยนรูปแบบด้วยตนเอง

การสนับสนุนเบราว์เซอร์

prefers-color-scheme

การรองรับเบราว์เซอร์

  • Chrome: 76
  • Edge: 79
  • Firefox: 67
  • Safari: 12.1

แหล่งที่มา

color-scheme

การรองรับเบราว์เซอร์

  • Chrome: 81.
  • Edge: 81
  • Firefox: 96
  • Safari: 13.

แหล่งที่มา

สไตล์ชีต User Agent

ก่อนจะไปต่อ เราขออธิบายสั้นๆ ว่าสไตล์ชีต User Agent คืออะไร โดยปกติแล้ว คุณอาจคิดว่าคำว่า User Agent (UA) เป็นคำพูดที่เก๋ไก๋สำหรับเบราว์เซอร์ สไตล์ชีต UA จะกําหนดลักษณะและอารมณ์เริ่มต้นของหน้าเว็บ สไตล์ชีตของ UA เป็นสิ่งที่ต้องอาศัย UA ที่เป็นปัญหา คุณสามารถดูสไตล์ชีต UA ของChrome (และ Chromium) และเปรียบเทียบกับของFirefox หรือSafari (และ WebKit) โดยทั่วไปแล้ว สไตล์ชีต UA จะตรงกันในเรื่องส่วนใหญ่ เช่น เว็บไซต์ทั้งหมดใช้ลิงก์สีน้ำเงิน ข้อความทั่วไปสีดํา และพื้นหลังสีขาว แต่ก็มีความแตกต่างที่สําคัญ (และบางครั้งก็น่ารําคาญ) เช่น การจัดรูปแบบตัวควบคุมแบบฟอร์ม

ดูรายละเอียดในสไตล์ชีต UA ของ WebKit และสิ่งที่ทำเกี่ยวกับโหมดมืด (ค้นหาข้อความ "dark" แบบเต็มในสไตล์ชีต) ค่าเริ่มต้นที่ได้จากสไตล์ชีตจะเปลี่ยนแปลงตามสถานะเปิดหรือปิดโหมดมืด ต่อไปนี้เป็นตัวอย่างกฎ CSS ที่ใช้คลาสจำลอง :matches และตัวแปรภายใน WebKit เช่น -apple-system-control-background รวมถึงคำสั่งของโปรแกรมประมวลผลข้อมูลล่วงหน้าภายใน WebKit อย่าง #if defined

input,
input:matches([type="password"], [type="search"]) {
  -webkit-appearance: textfield;
  #if defined(HAVE_OS_DARK_MODE_SUPPORT) &&
      HAVE_OS_DARK_MODE_SUPPORT
    color: text;
    background-color: -apple-system-control-background;
  #else
    background-color: white;
  #endif
  /* snip */
}

คุณจะเห็นค่าที่ไม่ใช่ค่ามาตรฐานสำหรับพร็อพเพอร์ตี้ color และ background-color ที่ด้านบน ทั้ง text และ -apple-system-control-background ไม่ใช่สี CSS ที่ถูกต้อง ซึ่งก็คือสีความหมายของ WebKit

แต่ CSS มีสีของระบบตามความหมายที่เป็นมาตรฐาน ซึ่งระบุไว้ในโมดูลสีของ CSS ระดับ 4 ตัวอย่างเช่น Canvas (อย่าสับสนกับแท็ก <canvas>) ใช้สำหรับพื้นหลังของเนื้อหาหรือเอกสารแอปพลิเคชัน ส่วน CanvasText ใช้สำหรับข้อความในเนื้อหาหรือเอกสารแอปพลิเคชัน 2 รายการนี้ใช้ร่วมกันได้และไม่ควรใช้แยกกัน

สไตล์ชีต UA สามารถใช้สีที่เป็นกรรมสิทธิ์ของตนเองหรือสีของระบบความหมายที่เป็นมาตรฐาน เพื่อกำหนดวิธีการแสดงผลองค์ประกอบ HTML โดยค่าเริ่มต้น หากระบบปฏิบัติการตั้งค่าเป็นโหมดมืดหรือใช้ธีมมืด ระบบจะตั้งค่า CanvasText (หรือ text) เป็นสีขาวแบบมีเงื่อนไข และตั้งค่า Canvas (หรือ -apple-system-control-background) เป็นสีดํา จากนั้นสไตลชีต UA จะกําหนด CSS ต่อไปนี้เพียงครั้งเดียว และครอบคลุมทั้งโหมดสว่างและโหมดมืด

/**
  Not actual UA stylesheet code.
  For illustrative purposes only.
*/
body {
  color: CanvasText;
  background-color: Canvas
}

พร็อพเพอร์ตี้ CSS color-scheme

ข้อกำหนดของโมดูลการปรับสี CSS ระดับ 1 แนะนำรูปแบบและการควบคุมการปรับสีอัตโนมัติโดย User Agent โดยมีวัตถุประสงค์เพื่อจัดการค่ากำหนดของผู้ใช้ เช่น โหมดมืด การปรับคอนทราสต์ หรือรูปแบบสีที่ต้องการ

พร็อพเพอร์ตี้ color-scheme ที่กําหนดไว้ช่วยให้องค์ประกอบระบุรูปแบบสีที่แสดงผลได้ ค่าเหล่านี้จะเจรจาต่อรองกับค่ากําหนดของผู้ใช้ ซึ่งจะส่งผลให้มีรูปแบบสีที่เลือกซึ่งส่งผลต่อสิ่งต่างๆ ในอินเทอร์เฟซผู้ใช้ (UI) เช่น สีเริ่มต้นของการควบคุมแบบฟอร์มและแถบเลื่อน รวมถึงค่าที่ใช้ของสีระบบ CSS ปัจจุบันระบบรองรับค่าต่อไปนี้

  • normal บ่งบอกว่าองค์ประกอบไม่รับรู้รูปแบบสีเลย ดังนั้นองค์ประกอบควรแสดงผลด้วยรูปแบบสีเริ่มต้นของเบราว์เซอร์

  • [ light | dark ]+ บ่งบอกว่าองค์ประกอบรับรู้และจัดการรูปแบบสีที่ระบุได้ และแสดงค่ากำหนดตามลำดับระหว่างรูปแบบสีเหล่านั้น

ในรายการนี้ light แสดงถึงรูปแบบสีอ่อน โดยมีสีพื้นหลังอ่อนและสีพื้นหน้าเข้ม ส่วน dark แสดงถึงรูปแบบสีเข้ม โดยมีสีพื้นหลังเข้มและสีพื้นหน้าอ่อน

สำหรับองค์ประกอบทั้งหมด การแสดงผลด้วยรูปแบบสีควรทําให้สีที่ใช้ใน UI ทั้งหมดที่เบราว์เซอร์ให้ไว้สําหรับองค์ประกอบนั้นตรงกับเจตนาของรูปแบบสี ตัวอย่างเช่น แถบเลื่อน การตรวจตัวสะกด ขีดเส้นใต้ การควบคุมแบบฟอร์ม ฯลฯ

ในองค์ประกอบ :root การแสดงผลด้วยรูปแบบสีจะต้องส่งผลต่อสีพื้นผิวของผืนผ้าใบ (นั่นคือสีพื้นหลังส่วนกลาง) ค่าเริ่มต้นของพร็อพเพอร์ตี้ color และค่าที่ใช้สำหรับสีของระบบ และควรส่งผลต่อแถบเลื่อนของวิวพอร์ตด้วย

/*
  The page supports both dark and light color schemes,
  and the page author prefers dark.
*/
:root {
  color-scheme: dark light;
}

เมตาแท็ก color-scheme

การปฏิบัติตามพร็อพเพอร์ตี้ CSS color-scheme กำหนดให้ต้องดาวน์โหลด CSS ก่อน (หากมีการอ้างอิงผ่าน <link rel="stylesheet">) และทำการแยกวิเคราะห์ คุณระบุค่า color-scheme ในองค์ประกอบ <meta name="color-scheme"> ได้เช่นกันเพื่อช่วย User Agent ในการเรนเดอร์พื้นหลังของหน้าเว็บด้วยรูปแบบสีที่ต้องการทันที

<!--
  The page supports both dark and light color schemes,
  and the page author prefers dark.
-->
<meta name="color-scheme" content="dark light">

รวม color-scheme และ prefers-color-scheme

เนื่องจากทั้งเมตาแท็กและพร็อพเพอร์ตี้ CSS (หากใช้กับองค์ประกอบ :root) จะให้ผลลัพธ์เหมือนกันในท้ายที่สุด เราจึงขอแนะนำให้ระบุรูปแบบสีผ่านเมตาแท็กเสมอ เพื่อให้เบราว์เซอร์ใช้รูปแบบที่ต้องการได้เร็วขึ้น

แม้ว่าหน้าฐานบรรทัดฐานสัมบูรณ์จะไม่ต้องใช้กฎ CSS เพิ่มเติม แต่ในกรณีทั่วไป คุณควรรวม color-scheme เข้ากับ prefers-color-scheme เสมอ ตัวอย่างเช่น สี -webkit-link ใน CSS ของ WebKit ซึ่งเป็นกรรมสิทธิ์ ซึ่ง WebKit และ Chrome ใช้สำหรับสีน้ำเงินแบบคลาสสิกของลิงก์ rgb(0,0,238) มีสัดส่วนคอนทราสต์ 2.23:1 ซึ่งไม่เพียงพอเมื่อใช้กับพื้นหลังสีดํา และไม่ผ่านทั้งข้อกําหนด WCAG AA และ WCAG AAA

เราได้เปิดข้อบกพร่องสำหรับ Chrome, WebKit และ Firefox รวมถึงปัญหาเกี่ยวกับเมตาในมาตรฐาน HTML เพื่อแก้ไขปัญหานี้

โต้ตอบกับ prefers-color-scheme

ความสัมพันธ์ระหว่างพร็อพเพอร์ตี้ CSS color-scheme และเมตาแท็กที่เกี่ยวข้องกับฟีเจอร์สื่อค่ากำหนดของผู้ใช้ prefers-color-scheme อาจดูสับสนในตอนแรก ความจริงแล้ว 2 อย่างนี้ทำงานร่วมกันได้ดีมากๆ สิ่งสำคัญที่สุดที่ควรทราบคือ color-schemeเป็นตัวกำหนดลักษณะที่ปรากฏเริ่มต้นแต่เพียงอย่างเดียว ส่วน prefers-color-scheme เป็นตัวกำหนดลักษณะที่ปรากฏที่กำหนดสไตล์ได้ เพื่อให้เข้าใจชัดเจนขึ้น ให้พิจารณาหน้าต่อไปนี้

<head>
  <meta name="color-scheme" content="dark light">
  <style>
    fieldset {
      background-color: gainsboro;
    }
    @media (prefers-color-scheme: dark) {
      fieldset {
        background-color: darkslategray;
      }
    }
  </style>
</head>
<body>
  <p>
    Lorem ipsum dolor sit amet, legere ancillae ne vis.
  </p>
  <form>
    <fieldset>
      <legend>Lorem ipsum</legend>
      <button type="button">Lorem ipsum</button>
    </fieldset>
  </form>
</body>

โค้ด CSS ในบรรทัดบนหน้าเว็บจะตั้งค่า background-color ขององค์ประกอบ <fieldset> เป็น gainsboro ในกรณีทั่วไป และตั้งค่าเป็น darkslategray หากผู้ใช้ต้องการใช้ชุดค่าผสมสี dark ตามฟีเจอร์สื่อค่ากำหนดของผู้ใช้ prefers-color-scheme

หน้าเว็บจะบอกเบราว์เซอร์ผ่านองค์ประกอบ <meta name="color-scheme" content="dark light"> ว่ารองรับธีมมืดและธีมสว่าง โดยระบุค่ากําหนดเป็นธีมมืด

หน้าเว็บทั้งหน้าจะปรากฏเป็นสีอ่อนบนพื้นหลังสีดําหรือในทางกลับกัน ทั้งนี้ขึ้นอยู่กับว่าระบบปฏิบัติการตั้งค่าเป็นโหมดมืดหรือโหมดสว่าง โดยอิงตามสไตล์ชีตของ User Agent ไม่มี CSS เพิ่มเติมที่นักพัฒนาซอฟต์แวร์ระบุไว้เพื่อเปลี่ยนข้อความย่อหน้าหรือสีพื้นหลังของหน้า

โปรดสังเกตว่า background-color ขององค์ประกอบ <fieldset> เปลี่ยนแปลงอย่างไร โดยอิงตามการเปิดใช้โหมดมืดหรือไม่ เป็นไปตามกฎในสไตล์ชีตแบบแทรกในหน้าเว็บที่นักพัฒนาซอฟต์แวร์ระบุ ซึ่งอาจเป็น gainsboro หรือ darkslategray

หน้าเว็บในโหมดสว่าง
โหมดสว่าง: รูปแบบที่นักพัฒนาแอปและ User Agent ระบุ ข้อความเป็นสีดําและพื้นหลังเป็นสีขาวตามสไตล์ชีตของ User Agent background-color ขององค์ประกอบ <fieldset> คือ gainsboro ตามสไตล์ชีตของนักพัฒนาแอปที่ฝังไว้
หน้าเว็บในโหมดมืด
โหมดมืด: รูปแบบที่นักพัฒนาแอปและ User Agent ระบุ ข้อความเป็นสีขาวและพื้นหลังเป็นสีดําตามสไตล์ชีตของ User Agent background-color ขององค์ประกอบ <fieldset> คือ darkslategray ตามสไตล์ชีตของนักพัฒนาแอปที่ฝังไว้

ลักษณะที่ปรากฏขององค์ประกอบ <button> ควบคุมโดยสไตล์ชีต User Agent color ได้รับการตั้งค่าเป็นสีของระบบ ButtonText และ background-color และ border-color ทั้ง 4 สีได้รับการตั้งค่าเป็นสีของระบบ ButtonFace

หน้าโหมดสว่างที่ใช้พร็อพเพอร์ตี้ ButtonFace
โหมดสว่าง: background-color และ border-color ต่างๆ ได้รับการตั้งค่าเป็นสีของระบบ ButtonFace

ตอนนี้ให้สังเกตว่า border-color ขององค์ประกอบ <button> เปลี่ยนแปลงอย่างไร ค่าที่คำนวณแล้วสำหรับ border-top-color และ border-bottom-color จะเปลี่ยนจาก rgba(0, 0, 0, 0.847) (สีดำ) เป็น rgba(255, 255, 255, 0.847) (สีขาว) เนื่องจาก User Agent จะอัปเดต ButtonFace แบบไดนามิกตามรูปแบบสี เช่นเดียวกับ color ขององค์ประกอบ <button> ที่กําหนดเป็นสีของระบบ ButtonText ที่เกี่ยวข้อง

แสดงว่าค่าสีที่คำนวณแล้วตรงกับ ButtonFace
โหมดสว่าง: ค่าที่คำนวณแล้วของ border-top-color และ border-bottom-color ซึ่งทั้ง 2 รายการตั้งค่าเป็น ButtonFace ในสไตล์ชีต User Agent เปลี่ยนเป็น rgba(0, 0, 0, 0.847) แล้ว
แสดงให้เห็นว่าค่าสีที่คำนวณยังคงตรงกับ ButtonFace ขณะอยู่ในโหมดมืด
โหมดมืด: ค่าที่คำนวณแล้วของ border-top-color และ border-bottom-color ซึ่งตั้งค่าไว้เป็น ButtonFace ในสไตล์ชีต User Agent เปลี่ยนเป็น rgba(255, 255, 255, 0.847) แล้ว

สาธิต

คุณดูเอฟเฟกต์ของ color-scheme ที่ใช้กับองค์ประกอบ HTML จำนวนมากได้ในการสาธิตเกี่ยวกับภาพแตก เดโมจงใจแสดงการละเมิด WCAG AA และ WCAG AAA ด้วยสีลิงก์ที่กล่าวถึงในคำเตือนด้านบน

การสาธิตขณะอยู่ในโหมดสว่าง
การสาธิต สลับเป็น color-scheme: light
การสาธิตขณะอยู่ในโหมดมืด
demo สลับเป็น color-scheme: dark โปรดทราบว่าการละเมิด WCAG AA และ WCAG AAA เกี่ยวข้องกับสีของลิงก์

ขอขอบคุณ

Rune Lillesveen เป็นผู้ติดตั้งใช้งานพร็อพเพอร์ตี้ CSS color-scheme และเมตาแท็กที่เกี่ยวข้อง Rune ยังเป็นผู้แก้ไขข้อกำหนดร่วมของข้อกำหนดการปรับสี CSS ระดับ 1 อีกด้วย รูปภาพหลักโดย Philippe Leone จาก Unsplash