Xây dựng bảng phối màu

Tổng quan cơ bản về cách thiết lập bảng phối màu động và có thể định cấu hình

Trong bài đăng này, tôi muốn chia sẻ cách quản lý nhiều bảng phối màu trong CSS. Xem bản minh hoạ.

Bản minh hoạ

Nếu bạn thích xem video hơn, sau đây là phiên bản của bài đăng này trên YouTube:

Tổng quan

Chúng ta sẽ xây dựng một hệ thống màu dễ tiếp cận bằng các thuộc tính tuỳ chỉnh và calc() để tạo ra một trang web thích ứng với tuỳ chọn của người dùng trong khi vẫn duy trì tối thiểu. Chúng tôi bắt đầu với màu sắc cơ bản của thương hiệu và xây dựng một hệ thống các biến thể khác nhau: 2 màu văn bản, 4 màu cho vùng hiển thị và 1 bóng đổ phù hợp.

Hướng dẫn này bắt đầu với việc xác định tất cả màu cho từng bảng phối màu . Không phải cho đến cuối cùng, chúng được sử dụng để thay đổi trang.

Thương hiệu

Thông thường, màu sắc thương hiệu đã được hình thành và được phân phối dưới dạng hex hoặc rgb. Thử thách GUI này có màu thương hiệu cơ bản là #0af. Trước tiên, đối với hệ thống màu này, giá trị hex nhu cầu được chuyển đổi thành hsl.

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

Để tạo ra khái niệm làm tối hoặc làm sáng màu thương hiệu, 20%, 3 kênh của giá trị màu hsl cần được trích xuất vào tùy chỉnh của riêng chúng các thuộc tính như sau:

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

CSS có thể giải toán dựa trên các thuộc tính màu đó, ví dụ: calc(var(--brand-lightness) - 20%) để giảm giá trị độ sáng đi 20%. Đây là nền tảng để xây dựng như CSS có thể giữ tất cả màu trong cùng một họ màu bằng cách điều chỉnh lượng bão hoà hsl và độ sáng.

Giao diện sáng

Mỗi biến thể màu sẽ được đánh dấu bằng bảng phối màu phù hợp, trong trường hợp này, mỗi biến thể được nối với -light.

bản xem trước kết quả kết thúc của giao diện sáng

Thương hiệu

Bắt đầu từ màu thương hiệu, thương hiệu sẽ được xây dựng lại bằng cách gói --brand-hue, --brand-saturation--brand-lightness thuộc tính tuỳ chỉnh bên trong ngoặc đơn hàm hsl (), mà không cần tính toán:

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

Màu văn bản

Tiếp theo, thành phần cơ bản của bảng phối màu cần có màu văn bản. Trong giao diện sáng, văn bản phải rất tối. Lưu ý độ sáng của các màu sau đây thấp, dưới 50%.

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

--text1-light, vì trời rất tối với độ sáng 10%, nên đèn có độ sáng 100% để màu sắc thương hiệu vẫn có thể nhìn được qua màu xanh nước biển đậm.

--text2-light, màu này không hoàn toàn tối như màu đầu tiên, tốt như màu này màu cấp hai và cũng có độ bão hoà ít hơn nhiều.

Màu cho vùng hiển thị

Màu sắc bề mặt là màu nền, đường viền và các bề mặt trang trí khác văn bản ở trên hoặc ở bên trong. Trong giao diện sáng, đây là những màu sáng như khác với màu văn bản tối màu. Cách tạo màu sáng bằng hsl: chúng ta sẽ sử dụng giá trị phần trăm cao hơn cho giá trị độ sáng thứ ba. Chúng tôi cũng sẽ giảm độ bão hoà, để màu xám nhạt trông không bị phủ quá nhiều.

* {
  --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 màu cho bề mặt được tạo vì các màu trang trí thường cần nhiều màu hơn cho các biến thể tương tác như :focus hoặc :hover hoặc để tạo sự xuất hiện của các lớp giấy. Trong những trường hợp này, bạn nên chuyển đổi --surface2-light khi di chuột đến --surface3-light, do đó, thao tác di chuột sẽ dẫn đến tăng độ tương phản (99% độ sáng lên 92% độ sáng; làm cho màu tối hơn).

Bóng

Bóng trong bảng phối màu là ở trên và cao hơn, nhưng thêm tính chất giống như thật cho hiệu ứng và giúp hình ảnh nổi bật khỏi bóng đen không thực tế. Việc cần làm thao tác này, màu của bóng sẽ sử dụng thuộc tính tuỳ chỉnh hue, hơi bão hoà màu nhưng vẫn rất tối. Về cơ bản, việc tạo nên một không gian tối bóng hơi xanh dương.

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

--surface-shadow-light không được gói trong một hàm hsl. Điều này là do Giá trị --shadow-strength sẽ được kết hợp để tạo ra một độ mờ và cần CSS các mảnh ghép để thực hiện phép tính. Chuyển đến bóng Rad để tìm hiểu thêm.

Các màu ánh sáng kết hợp cùng nhau

Không cần phải săn tìm khắp nơi để tìm ra cách tạo ra các màu sáng, chúng tất cả ở cùng một nơi trong 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;
}
ảnh chụp màn hình các màu ánh sáng cùng nhau
Hộp cát trên CodePen

Giao diện tối

Hầu hết các thương hiệu không bắt đầu bằng giao diện tối, đây là một biến thể của giao diện chính, thường nhẹ nhàng hơn. Mặt khác, người dùng thường chọn giao diện tối cho các bối cảnh khác nhau, như ban đêm. Chính những yếu tố này đã giúp tôi giữ hai những điều cần lưu ý đối với giao diện tối:

  1. Người dùng thường ở chế độ tối khi sử dụng giao diện này, vì vậy hãy kiểm thử trong tối.
  2. Màu sắc phải giảm độ rực màu để không rung trên màn hình do quá mãnh liệt.

bản xem trước kết quả cuối cùng của giao diện tối

Thương hiệu

Giao diện sáng sử dụng 3 giá trị kênh màu hsl thương hiệu mà không thay đổi, giao diện tối thì không. Độ bão hoà giảm đi một nửa và độ sáng giảm 50%.

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

Màu văn bản

Trong giao diện tối, màu văn bản phải là màu sáng. Các màu sau có chất lượng cao các giá trị về độ sáng, làm cho chúng gần với màu trắng hơn.

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

Màu cho vùng hiển thị

Trong giao diện tối, màu của bề mặt phải là màu tối. Các màu sau có độ sáng và độ bão hoà thấp, với bề mặt đầu tiên là tối nhất với 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%);
}

Bóng

Trong giao diện tối, người dùng có thể rất khó nhìn thấy bóng. Hợp lý vì khó mà làm tối thứ gì đó đã khá tối. Đây là nơi --shadow-strength-dark rất hữu ích vì nó cho phép chúng ta làm tối bóng bằng cách thay đổi một biến.

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

Ngoài ra, hãy xem độ bão hoà trong bóng đó. Bạn có nhận thấy màu sắc không khi bạn nhìn vào giao diện? Hãy thử loại bỏ độ bão hoà khỏi devtools nào, bạn thích công cụ nào hơn?!

Tất cả màu tối

* {
  --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;
}
ảnh chụp màn hình các màu tối
Hộp cát trên CodePen

Giảm độ sáng của giao diện

Bảng phối màu này tập trung vào việc phối hợp độ sáng và độ rực màu. Có cần có đủ độ bão hoà để vẫn hiển thị được sắc độ, nhưng cũng nên chỉ vượt qua điểm tương phản vì nhằm mục đích giảm độ sáng và độ tương phản thấp.

bản xem trước các kết quả cuối cùng trong giao diện tối

Thương hiệu

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

Màu văn bản

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

Màu cho vùng hiển thị

* {
  --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%);
}

Bóng

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

Giảm độ sáng cùng nhau

* {
  --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;
}
ảnh chụp màn hình các màu tối
Hộp cát trên CodePen

Màu hỗ trợ tiếp cận

Lưu ý cách độ sáng thấp nhất trong tập hợp màu văn bản tối là 65% và độ sáng cao nhất trên các bề mặt tối là 25%. Ánh sáng nhẹ nhàng là 40% khoảng thở giữa hai người. Trong giao diện sáng, 55% không gian hít thở giao diện sáng. Duy trì sự khác biệt về độ sáng giữa văn bản và màu cho vùng hiển thị ở khoảng 40-50% có thể giúp duy trì tỷ lệ tương phản màu cao, đồng thời cũng là đòn bẩy tinh tế để điều chỉnh trong trường hợp điểm số kém.

Tôi gọi đó là "lượt va đập giá trị độ nhẹ cho đến khi công cụ cho thấy tôi đang truyền.

nhấn shift + mũi tên xuống để giảm độ sáng và tăng độ tương phản cho đến khi qua

Mỗi giao diện được tạo trong thử thách này đều đạt điểm tương phản. Bảng phối màu mờ có độ tương phản thấp nhất, nhưng vẫn đáp ứng được các yêu cầu tối thiểu. Để giúp những người khác trong nhóm sử dụng màu sắc tương phản hiệu quả, bạn nên tạo một tên lớp có khả năng ghép màu giữa màu bề mặt với màu văn bản dễ tiếp cận.

.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);
}
Ảnh chụp màn hình ghép nối văn bản và bề mặt làm mờ
Ảnh chụp màn hình ghép nối văn bản và bề mặt làm mờ với VisBug

Bóng Rad

Các giao diện sử dụng một lớp tiện ích có tên là .rad-shadow. Bóng này đã được tạo tại công cụ Shadow Shadow mà tôi rất đánh giá cao rất nhiều. Tôi lấy đoạn mã được tạo và tuỳ chỉnh đoạn mã đó bằng màu của riêng mình và tính toán độ mờ. Lý do cho điều này là để tạo ra một bóng mà tôi có thể điều chỉnh trong từng bảng phối màu.

từng bóng đổ cạnh nhau

Để thực hiện điều này, tôi đã tạo 2 biến cho mỗi bảng phối màu để điều chỉnh, một biến màu bóng và độ mạnh của bóng. Màu dành cho độ rực màu và độ tối còn độ mạnh là một cách dễ dàng để tăng độ bóng cường độ khi đó là bảng phối màu tối. Kết quả cuối cùng có dạng như sau.

: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))
  ;
}

Nếu tôi sử dụng thêm các bóng đổ trong bảng phối màu, tôi sẽ tạo bóng đổ góc cũng như hằng số mã thông báo thiết kế, vì hướng ánh sáng phải giống nhau giữa tất cả các bóng của thiết kế.

Sử dụng bảng phối màu

Sau khi việc xác định trước màu sắc đã hoàn tất, đã đến lúc biến chúng thành các thuộc tính bất khả kiến của lược đồ. Ý tôi là, với tư cách là một CSS tác giả bên trong dự án bảng phối màu này, người dùng hiếm khi cần truy cập vào giá trị của bảng phối màu cụ thể. Tôi muốn giúp bạn dễ dàng hoà nhập vào chủ đề.

Để thực hiện điều này, bạn chỉ nên sử dụng bảng phối màu thông qua mà chúng ta sẽ xác định ngay sau đây. Bằng cách này, những người sử dụng biến thiết kế không bao giờ cần phải quan tâm xem bảng phối màu nào hiện được đặt, họ chỉ cần sử dụng màu cho vùng hiển thị và văn bản. Thay vì color: var(--text1-light) sử dụng color: var(--text1). Tất cả việc điều chỉnh và chuyển hướng màu sắc được thực hiện ở cấp cao hơn nhiều trong CSS.

Đi sâu vào, kiểu liên kết của giao diện sáng trong khối mã dưới đây, kết nối một thuộc tính tuỳ chỉnh chung với màu cụ thể của giao diện sáng. Hiện đã có tất cả việc sử dụng var(--brand) sẽ sử dụng màu sáng của thương hiệu.

Giao diện sáng (tự động)

: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);
}

Trang web này đang dùng giao diện sáng. Đây là một khoảnh khắc rất thành công! Hãy xem thêm một vài khoảnh khắc đó khi chúng ta sử dụng các màu được xác định trước trong ngữ cảnh bảng phối màu.

Giao diện tối (tự động)

@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);
  }
}

Giao diện sáng

[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);
}

Giao diện tối

[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);
}

Giảm độ sáng của giao diện

[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);
}

Tại thời điểm này, tác giả có thể tuỳ ý sử dụng bảng phối màu chung được cung cấp như cần thiết và không bao giờ phải lo lắng về giao diện nữa.

Kết luận

Giờ bạn đã biết cách tôi thực hiện điều đó, bạn sẽ làm thế nào?! 🙂

Hãy đa dạng hoá phương pháp tiếp cận và tìm hiểu tất cả các cách xây dựng ứng dụng trên web. Tạo một Codepen hoặc lưu trữ bản minh hoạ của riêng bạn, tweet cho tôi và tôi sẽ thêm nó vào Phần bên dưới là phần các bản phối lại của cộng đồng.

Nguồn

Bản phối lại của cộng đồng - @chris-kruining đã thêm một thanh trượt màu sắc, màu trạng thái và chế độ tương phản cho no-preference, moreless: bản minh hoạ.