การสร้างรูปแบบสี

ภาพรวมพื้นฐานเกี่ยวกับวิธีสร้างรูปแบบสีแบบไดนามิกและกำหนดค่าได้

ในโพสต์นี้ เราอยากแชร์แนวคิดเกี่ยวกับวิธีจัดการรูปแบบสีหลายรูปแบบใน CSS ลองใช้เวอร์ชันเดโม

สาธิต

หากคุณชอบดูวิดีโอมากกว่า เรามีโพสต์นี้ในเวอร์ชัน YouTube ด้วย

ภาพรวม

เราจะสร้างระบบสีที่เข้าถึงได้ด้วยพร็อพเพอร์ตี้ที่กำหนดเองและ calc() เพื่อสร้างหน้าเว็บที่ปรับเปลี่ยนตามค่ากำหนดของผู้ใช้โดยที่ยังคงประสบการณ์การเขียนโค้ดที่เรียบง่ายไว้ เราเริ่มต้นด้วยสีแบรนด์พื้นฐานและสร้างระบบของตัวแปรจากสีดังกล่าว ซึ่งประกอบด้วยสีข้อความ 2 สี สีพื้นผิว 4 สี และเงาที่เข้ากัน

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

แบรนด์

บ่อยครั้งที่สีของแบรนด์ได้รับการกำหนดไว้แล้วและแสดงเป็น hex หรือ rgb ชาเลนจ์ GUI นี้ มีสีแบรนด์พื้นฐานเป็น #0af ก่อนอื่น สำหรับระบบสีนี้ ค่าฐานสิบหก ต้องแปลงเป็น hsl

* {
  --brand: #0af;
  --brand: hsl(200 100% 50%);
}

หากต้องการเปิดใช้แนวคิดการทำให้สีของแบรนด์เข้มขึ้นหรือสว่างขึ้น เช่น 20% คุณต้องแยกช่อง 3 ช่องของค่าสี hsl ออกเป็นพร็อพเพอร์ตี้ที่กำหนดเอง ดังนี้

* {
  --brand-hue: 200;
  --brand-saturation: 100%;
  --brand-lightness: 50%;
}

CSS สามารถคำนวณพร็อพเพอร์ตี้สีเหล่านั้นได้ เช่น calc(var(--brand-lightness) - 20%) เพื่อลดค่าความสว่างลง 20% ซึ่งเป็นพื้นฐานในการสร้างรูปแบบสี เนื่องจาก CSS สามารถเก็บสีทั้งหมดไว้ในตระกูลสีเดียวกันได้โดยการปรับปริมาณความอิ่มตัวและความสว่างของ HSL

ธีมสว่าง

ระบบจะทำเครื่องหมายตัวแปรสีแต่ละรายการด้วยรูปแบบที่ตรงกัน ในกรณีนี้ ระบบจะเพิ่ม -light ต่อท้ายแต่ละรายการ

ตัวอย่างผลลัพธ์สุดท้ายของธีมสว่าง

แบรนด์

โดยเริ่มจากสีของแบรนด์ ซึ่งสร้างขึ้นใหม่โดยการรวมคุณสมบัติที่กำหนดเอง --brand-hue, --brand-saturation และ --brand-lightness ไว้ในวงเล็บฟังก์ชัน hsl () โดยไม่มีการคำนวณใดๆ ดังนี้

* {
  --brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
}

สีข้อความ

ถัดไป สิ่งสำคัญของรูปแบบสีคือต้องมีสีข้อความ ในธีมสว่าง ข้อความควรเป็นสีเข้มมาก สังเกตว่าความสว่างของสีต่อไปนี้ต่ำ ต่ำกว่า 50% มาก

* {
  --text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
  --text2-light: hsl(var(--brand-hue) 30% 30%);
}

--text1-light เนื่องจากมีความมืดมากที่ความสว่าง 10% จึงคงความอิ่มตัวของสีไว้ที่ 100% เพื่อให้สีของแบรนด์ยังคงมองเห็นได้ในสีกรมท่าที่มืดสนิท

--text2-light สีนี้ไม่เข้มเท่าสีแรก ซึ่งก็ดีเพราะเป็นสีรอง และยังมีความอิ่มตัวน้อยกว่ามากด้วย

สีของพื้นผิว

สีของพื้นผิวคือพื้นหลัง เส้นขอบ และพื้นผิวตกแต่งอื่นๆ ที่มีข้อความอยู่ด้านบนหรือด้านใน ในธีมสว่าง สีเหล่านี้จะเป็นสีอ่อน ซึ่งตรงข้ามกับสีข้อความที่เป็นสีเข้ม หากต้องการสร้างสีอ่อนด้วย hsl เราจะใช้ค่าเปอร์เซ็นต์ที่สูงขึ้นในค่าความสว่างที่ 3 เราจะลดความอิ่มตัวของสีด้วย เพื่อไม่ให้สีเทาอ่อนดูมีสีมากเกินไป

* {
  --surface1-light: hsl(var(--brand-hue) 25% 90%);
  --surface2-light: hsl(var(--brand-hue) 20% 99%);
  --surface3-light: hsl(var(--brand-hue) 20% 92%);
  --surface4-light: hsl(var(--brand-hue) 20% 85%);
}

มีการสร้างสีพื้นผิว 4 สีเนื่องจากสีตกแต่งมักต้องการตัวแปรมากกว่า สำหรับช่วงเวลาที่มีการโต้ตอบ เช่น :focus หรือ :hover หรือเพื่อสร้างลักษณะของเลเยอร์กระดาษ ในสถานการณ์เหล่านี้ การเปลี่ยน --surface2-light เป็น --surface3-light เมื่อวางเมาส์เหนือองค์ประกอบจะช่วยให้การวางเมาส์เหนือองค์ประกอบส่งผลให้คอนทราสต์เพิ่มขึ้น (ความสว่าง 99% เป็นความสว่าง 92% ซึ่งทำให้มืดลง)

เงา

เงาภายในรูปแบบสีเป็นสิ่งที่เหนือความคาดหมาย แต่ช่วยเพิ่มความเป็นธรรมชาติที่สมจริงให้กับเอฟเฟกต์และช่วยให้โดดเด่นกว่าเงาที่ใช้สีดำซึ่งไม่สมจริง โดยสีของเงาจะใช้พร็อพเพอร์ตี้ที่กำหนดเองของสี โดยจะมีความอิ่มตัวเล็กน้อยด้วยสี แต่ยังคงมืดมาก โดยพื้นฐานแล้วคือการสร้างเงาสีน้ำเงินเล็กน้อยที่มืดมาก

* {
  --surface-shadow-light: var(--brand-hue) 10% 20%;
  --shadow-strength-light: .02;
}

--surface-shadow-light ไม่ได้รวมอยู่ในฟังก์ชัน hsl เนื่องจากค่า --shadow-strength จะรวมกันเพื่อสร้างความทึบแสง และ CSS ต้องใช้ส่วนต่างๆ เพื่อทำการคำนวณ ข้ามไปที่ส่วนเงาที่สวยงามเพื่อดูข้อมูลเพิ่มเติม

สีไฟทั้งหมดพร้อมกัน

คุณไม่จำเป็นต้องค้นหาว่าสีอ่อนแต่ละสีสร้างขึ้นอย่างไร เนื่องจากสีทั้งหมดอยู่ในที่เดียวใน CSS

* {
  --brand-light: hsl(var(--brand-hue) var(--brand-saturation) var(--brand-lightness));
  --text1-light: hsl(var(--brand-hue) var(--brand-saturation) 10%);
  --text2-light: hsl(var(--brand-hue) 30% 30%);
  --surface1-light: hsl(var(--brand-hue) 25% 90%);
  --surface2-light: hsl(var(--brand-hue) 20% 99%);
  --surface3-light: hsl(var(--brand-hue) 20% 92%);
  --surface4-light: hsl(var(--brand-hue) 20% 85%);
  --surface-shadow-light: var(--brand-hue) 10% calc(var(--brand-lightness) / 5);
  --shadow-strength-light: .02;
}
ภาพหน้าจอของสีอ่อนทั้งหมดรวมกัน
แซนด์บ็อกซ์ใน CodePen

ธีมมืด

แบรนด์ส่วนใหญ่ไม่ได้เริ่มต้นด้วยธีมมืด แต่เป็นตัวแปรของธีมหลักซึ่งมักจะสว่างกว่า ในทางกลับกัน ผู้ใช้มักจะเลือกธีมมืดสำหรับบริบทที่แตกต่างกัน เช่น เวลากลางคืน ปัจจัยเหล่านี้ทำให้ฉันต้องคำนึงถึง 2 สิ่งต่อไปนี้เมื่อใช้ธีมมืด

  1. โดยทั่วไปผู้ใช้จะอยู่ในที่มืดขณะใช้ธีมนี้ ดังนั้นให้ทดสอบในที่มืด
  2. สีควรลดความอิ่มตัวลงเพื่อไม่ให้สั่นบนหน้าจอเนื่องจากมีความเข้มมากเกินไป

ตัวอย่างผลลัพธ์สุดท้ายของธีมมืด

แบรนด์

ธีมสว่างใช้ค่าช่องสี HSL ของแบรนด์ 3 ค่าโดยไม่มีการเปลี่ยนแปลง ส่วนธีมมืดไม่ได้ใช้ ความอิ่มตัวจะลดลงครึ่งหนึ่งและความสว่างลดลง 50% แบบสัมพัทธ์

* {
  --brand-dark: hsl(
    var(--brand-hue)
    calc(var(--brand-saturation) / 2)
    calc(var(--brand-lightness) / 1.5)
  );
}

สีข้อความ

ในธีมมืด สีข้อความควรเป็นสีอ่อน สีต่อไปนี้มีค่าความสว่างสูง ซึ่งทำให้สีใกล้เคียงกับสีขาวมากขึ้น

* {
  --text1-dark: hsl(var(--brand-hue) 15% 85%);
  --text2-dark: hsl(var(--brand-hue) 5% 65%);
}

สีของพื้นผิว

ในธีมมืด สีของพื้นผิวควรเป็นสีเข้ม สีต่อไปนี้มีความสว่างและความอิ่มตัวต่ำ โดยพื้นผิวที่ 1 มีความมืดที่สุดที่ 10%

* {
  --surface1-dark: hsl(var(--brand-hue) 10% 10%);
  --surface2-dark: hsl(var(--brand-hue) 10% 15%);
  --surface3-dark: hsl(var(--brand-hue) 5%  20%);
  --surface4-dark: hsl(var(--brand-hue) 5% 25%);
}

เงา

ในธีมมืด เงาอาจมองเห็นได้ยากมาก ซึ่งก็สมเหตุสมผลเพราะการทำให้สิ่งที่มืดอยู่แล้วมืดลงไปอีกนั้นทำได้ยาก --shadow-strength-dark จึงมีประโยชน์มาก เพราะช่วยให้เราทำให้เงาเข้มขึ้นได้โดยการเปลี่ยนตัวแปรเดียว

* {
  --surface-shadow-dark: var(--brand-hue) 50% 3%;
  --shadow-strength-dark: .8;
}

นอกจากนี้ ให้ดูว่าเงามีความอิ่มตัวมากเพียงใด คุณสังเกตเห็นสีไหม เมื่อดูอินเทอร์เฟซ ลองนำความอิ่มตัวออกจากเครื่องมือสำหรับนักพัฒนาเว็บ คุณชอบแบบไหนมากกว่ากัน

สีเข้มทั้งหมดรวมกัน

* {
  --brand-dark: hsl(var(--brand-hue) calc(var(--brand-saturation) / 2) calc(var(--brand-lightness) / 1.5));
  --text1-dark: hsl(var(--brand-hue) 15% 85%);
  --text2-dark: hsl(var(--brand-hue) 5% 65%);
  --surface1-dark: hsl(var(--brand-hue) 10% 10%);
  --surface2-dark: hsl(var(--brand-hue) 10% 15%);
  --surface3-dark: hsl(var(--brand-hue) 5%  20%);
  --surface4-dark: hsl(var(--brand-hue) 5% 25%);
  --surface-shadow-dark: var(--brand-hue) 50% 3%;
  --shadow-strength-dark: .8;
}
ภาพหน้าจอของสีเข้มทั้งหมดรวมกัน
แซนด์บ็อกซ์ใน CodePen

ธีมมืด

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

ตัวอย่างผลลัพธ์สุดท้ายจากธีมมืด

แบรนด์

* {
  --brand-dim: hsl(
    var(--brand-hue)
    calc(var(--brand-saturation) / 1.25)
    calc(var(--brand-lightness) / 1.25)
  );
}

สีข้อความ

* {
  --text1-dim: hsl(var(--brand-hue) 15% 75%);
  --text2-dim: hsl(var(--brand-hue) 10% 61%);
}

สีของพื้นผิว

* {
  --surface1-dim: hsl(var(--brand-hue) 10% 20%);
  --surface2-dim: hsl(var(--brand-hue) 10% 25%);
  --surface3-dim: hsl(var(--brand-hue) 5%  30%);
  --surface4-dim: hsl(var(--brand-hue) 5% 35%);
}

เงา

* {
  --surface-shadow-dim: var(--brand-hue) 30% 13%;
  --shadow-strength-dim: .2;
}

หรี่สีทั้งหมดพร้อมกัน

* {
  --brand-dim: hsl(var(--brand-hue) calc(var(--brand-saturation) / 1.25) calc(var(--brand-lightness) / 1.25));
  --text1-dim: hsl(var(--brand-hue) 15% 75%);
  --text2-dim: hsl(var(--brand-hue) 10% 61%);
  --surface1-dim: hsl(var(--brand-hue) 10% 20%);
  --surface2-dim: hsl(var(--brand-hue) 10% 25%);
  --surface3-dim: hsl(var(--brand-hue) 5%  30%);
  --surface4-dim: hsl(var(--brand-hue) 5% 35%);
  --surface-shadow-dim: var(--brand-hue) 30% 13%;
  --shadow-strength-dim: .2;
}
ภาพหน้าจอของสีที่หม่นทั้งหมดรวมกัน
แซนด์บ็อกซ์ใน CodePen

สีที่เข้าถึงได้

โปรดสังเกตว่าความสว่างต่ำสุดในชุดสีข้อความมืดคือ 65% และความสว่างสูงสุดในพื้นผิวมืดคือ 25% ซึ่งเป็นพื้นที่ว่าง 40% ของความสว่างระหว่างสีทั้งสอง ในธีมสว่าง จะมีพื้นที่ว่าง 55% ในธีมสว่าง การรักษาความแตกต่างของความสว่างระหว่างข้อความและสีพื้นผิวไว้ที่ประมาณ 40-50% จะช่วยรักษาอัตราส่วนคอนทราสต์ของสีให้สูงได้ และยังเป็นตัวปรับที่ละเอียดอ่อนในกรณีที่คะแนนต่ำด้วย

ฉันเรียกวิธีนี้ว่า "เพิ่มค่าไปเรื่อยๆ จนกว่าจะผ่าน" ซึ่งเป็นการเพิ่มค่าความสว่างไปเรื่อยๆ จนกว่าเครื่องมือจะแสดงว่าผ่าน

กด Shift + ลูกศรลงเพื่อลดความสว่างและเพิ่มคอนทราสต์จนกว่าจะผ่าน

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

.surface1 {
  background-color: var(--surface1);
  color: var(--text2);
}

.surface2 {
  background-color: var(--surface2);
  color: var(--text2);
}

.surface3 {
  background-color: var(--surface3);
  color: var(--text1);
}

.surface4 {
  background-color: var(--surface4);
  color: var(--text1);
}
ภาพหน้าจอของพื้นผิวที่มืดและการจับคู่ข้อความ
ภาพหน้าจอของพื้นผิวสีทึบและการจับคู่ข้อความกับ VisBug

Rad Shadow

ธีมใช้คลาสยูทิลิตีชื่อ .rad-shadow เงาที่เห็นนี้สร้างขึ้นด้วยเครื่องมือ Smooth Shadow ซึ่งผมชอบมาก ฉันนำข้อมูลโค้ดที่สร้างขึ้นมาและปรับแต่งด้วยสีและการคำนวณความทึบแสงของฉันเอง เหตุผลที่ทำเช่นนี้คือเพื่อสร้างเงาที่ฉันสามารถปรับได้ภายในรูปแบบสีแต่ละแบบ

เงาแต่ละเงาอยู่ติดกัน

เพื่อดำเนินการนี้ ฉันได้สร้างตัวแปร 2 ตัวสำหรับรูปแบบสีแต่ละแบบที่จะปรับ ได้แก่ สีเงาและความเข้มของเงา สีใช้สำหรับการปรับความอิ่มตัวและความมืด ส่วนความเข้มใช้เพื่อเพิ่มความเข้มของเงาได้ง่ายๆ เมื่อใช้รูปแบบสีมืด ผลลัพธ์สุดท้ายที่ได้ก็จะเป็นแบบนี้

:root {
  --surface-shadow-light: var(--brand-hue) 10% 20%;
  --shadow-strength-light: .02;
}

.rad-shadow {
  box-shadow:
    0 2.8px 2.2px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
    0 6.7px 5.3px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .01)),
    0 12.5px 10px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
    0 22.3px 17.9px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .02)),
    0 41.8px 33.4px hsl(var(--surface-shadow) / calc(var(--shadow-strength) + .03)),
    0 100px 80px hsl(var(--surface-shadow) / var(--shadow-strength))
  ;
}

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

การใช้รูปแบบสี

เมื่อกำหนดสีล่วงหน้าเสร็จแล้ว ก็ถึงเวลาเปลี่ยนสีเหล่านั้นให้เป็นพร็อพเพอร์ตี้ที่ไม่ขึ้นอยู่กับรูปแบบ สิ่งที่ฉันหมายถึงคือในฐานะผู้เขียน CSS ในโปรเจ็กต์รูปแบบสีนี้ เราไม่ค่อยจำเป็นต้องเข้าถึงค่าของรูปแบบสีที่เฉพาะเจาะจง ฉันอยากให้การจัดรูปแบบสอดคล้องกับธีมเป็นเรื่องง่าย

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

เมื่อเจาะลึกเข้าไป รูปแบบการเชื่อมต่อของธีมสว่างในโค้ดบล็อกต่อไปนี้จะเชื่อมต่อคุณสมบัติที่กำหนดเองทั่วไปกับสีเฉพาะของธีมสว่าง ตอนนี้การใช้ var(--brand) ทั้งหมดจะใช้สีอ่อนของแบรนด์

ธีมสว่าง (อัตโนมัติ)

:root {
  color-scheme: light;
  --brand: var(--brand-light);
  --text1: var(--text1-light);
  --text2: var(--text2-light);
  --surface1: var(--surface1-light);
  --surface2: var(--surface2-light);
  --surface3: var(--surface3-light);
  --surface4: var(--surface4-light);
  --surface-shadow: var(--surface-shadow-light);
  --shadow-strength: var(--shadow-strength-light);
}

ตอนนี้เว็บไซต์ใช้ธีมสว่างแล้ว นี่เป็นช่วงเวลาแห่งความสำเร็จที่สนุกมาก มาดูตัวอย่างเพิ่มเติมกันว่าเราจะใช้สีที่กำหนดไว้ล่วงหน้าในบริบทรูปแบบสีอื่นๆ ได้อย่างไร

ธีมมืด (อัตโนมัติ)

@media (prefers-color-scheme: dark) {
  :root {
    color-scheme: dark;

    --brand: var(--brand-dark);
    --text1: var(--text1-dark);
    --text2: var(--text2-dark);
    --surface1: var(--surface1-dark);
    --surface2: var(--surface2-dark);
    --surface3: var(--surface3-dark);
    --surface4: var(--surface4-dark);
    --surface-shadow: var(--surface-shadow-dark);
    --shadow-strength: var(--shadow-strength-dark);
  }
}

ธีมสว่าง

[color-scheme="light"] {
  color-scheme: light;

  --brand: var(--brand-light);
  --text1: var(--text1-light);
  --text2: var(--text2-light);
  --surface1: var(--surface1-light);
  --surface2: var(--surface2-light);
  --surface3: var(--surface3-light);
  --surface4: var(--surface4-light);
  --surface-shadow: var(--surface-shadow-light);
  --shadow-strength: var(--shadow-strength-light);
}

ธีมมืด

[color-scheme="dark"] {
  color-scheme: dark;

  --brand: var(--brand-dark);
  --text1: var(--text1-dark);
  --text2: var(--text2-dark);
  --surface1: var(--surface1-dark);
  --surface2: var(--surface2-dark);
  --surface3: var(--surface3-dark);
  --surface4: var(--surface4-dark);
  --surface-shadow: var(--surface-shadow-dark);
  --shadow-strength: var(--shadow-strength-dark);
}

ธีมมืด

[color-scheme="dim"] {
  color-scheme: dark;

  --brand: var(--brand-dim);
  --text1: var(--text1-dim);
  --text2: var(--text2-dim);
  --surface1: var(--surface1-dim);
  --surface2: var(--surface2-dim);
  --surface3: var(--surface3-dim);
  --surface4: var(--surface4-dim);
  --surface-shadow: var(--surface-shadow-dim);
  --shadow-strength: var(--shadow-strength-dim);
}

ในตอนนี้ ผู้เขียนสามารถใช้รูปแบบสีทั่วไปที่ให้มาได้ตามต้องการ และไม่ต้องกังวลเรื่องธีมอีกต่อไป

บทสรุป

ตอนนี้คุณก็รู้แล้วว่าเราทำยังไง แล้วคุณล่ะจะทำยังไง 🙂

มาลองใช้วิธีการที่หลากหลายและเรียนรู้วิธีทั้งหมดในการสร้างบนเว็บกัน สร้าง Codepen หรือโฮสต์เดโมของคุณเอง ทวีตมาหาฉัน แล้วฉันจะเพิ่มลงในส่วนรีมิกซ์ของชุมชนด้านล่าง

แหล่งที่มา

รีมิกซ์จากชุมชน - @chris-kruining เพิ่มแถบเลื่อนโทนสี สีสถานะ และโหมดคอนทราสต์สำหรับ no-preference, more และ less: เดโม