Membuat skema warna

Ringkasan dasar tentang cara membuat skema warna dinamis dan dapat dikonfigurasi

Dalam postingan ini, saya ingin berbagi pemikiran tentang cara mengelola beberapa skema warna di CSS. Coba demo.

Demo

Jika Anda lebih suka video, berikut versi YouTube dari postingan ini:

Ringkasan

Kita akan membuat sistem warna yang mudah diakses dengan properti kustom dan calc(), untuk membuat halaman web yang adaptif terhadap preferensi pengguna sekaligus menjaga pengalaman penulisan tetap minimal. Kita mulai dengan warna merek dasar dan membangun sistem varian darinya: 2 warna teks, 4 warna permukaan, dan bayangan yang cocok.

Panduan ini dimulai dengan menentukan semua warna untuk setiap skema warna di awal. Tidak sampai di bagian akhir, tombol tersebut digunakan untuk mengubah halaman.

Brand

Sering kali, warna merek telah ditetapkan dan diberikan sebagai hex atau rgb. Tantangan GUI ini memiliki warna merek dasar #0af. Pertama, untuk sistem warna ini, nilai hex perlu dikonversi menjadi hsl.

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

Untuk mengaktifkan konsep menggelapkan atau mencerahkan warna merek, misalnya sebesar 20%, 3 saluran nilai warna hsl perlu diekstrak ke dalam properti kustomnya sendiri, seperti ini:

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

CSS dapat melakukan perhitungan pada properti warna tersebut, misalnya calc(var(--brand-lightness) - 20%) untuk mengurangi nilai kecerahan sebesar 20%. Hal ini mendasar untuk membangun skema warna karena CSS dapat mempertahankan semua warna dalam keluarga warna yang sama dengan menyesuaikan jumlah saturasi dan kecerahan hsl.

Tema terang

Setiap varian warna akan ditandai dengan skema yang cocok, dalam hal ini, setiap varian warna ditambahkan dengan -light.

pratinjau hasil akhir tema terang

Merek

Dimulai dengan warna merek, komponen ini dibangun ulang dengan membungkus properti kustom --brand-hue, --brand-saturation, dan --brand-lightness di dalam tanda kurung fungsi hsl (), tanpa perhitungan apa pun:

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

Warna teks

Selanjutnya, elemen penting skema warna memerlukan warna teks. Dalam tema terang, teks harus sangat gelap. Perhatikan bagaimana kecerahan warna berikut rendah, jauh di bawah 50%.

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

--text1-light, karena sangat gelap pada kecerahan 10%, tetap mempertahankan saturasi 100% yang berat sehingga warna merek masih dapat terlihat di dalam warna biru tua yang sangat gelap.

--text2-light, tidak terlalu gelap seperti warna pertama, yang bagus karena merupakan warna sekunder, dan juga jauh kurang jenuh.

Warna permukaan

Warna permukaan adalah latar belakang, batas, dan permukaan dekoratif lainnya yang menjadi tempat atau di dalam teks. Dalam tema terang, ini adalah warna terang, berbeda dengan warna teks yang gelap. Untuk membuat warna terang dengan hsl, kita akan menggunakan nilai persentase yang lebih tinggi dalam nilai kecerahan ketiga. Kita juga akan menurunkan saturasi, sehingga warna abu-abu muda tidak terlihat terlalu berwarna.

* {
  --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 warna permukaan dibuat karena warna dekoratif cenderung memerlukan lebih banyak varian, untuk momen interaktif seperti :focus atau :hover atau untuk menciptakan tampilan lapisan kertas. Dalam skenario ini, akan lebih baik jika transisi --surface2-light saat kursor diarahkan ke --surface3-light, sehingga saat kursor diarahkan akan menghasilkan peningkatan kontras (kecerahan 99% menjadi kecerahan 92%; membuatnya lebih gelap).

Bayangan

Bayangan dalam skema warna sangatlah penting, tetapi menambahkan sifat seperti aslinya pada efek dan membantu efek tersebut terlihat berbeda dari bayangan berbasis hitam yang tidak realistis. Untuk melakukannya, warna bayangan akan menggunakan properti kustom hue, sedikit jenuh dengan hue, tetapi tetap sangat gelap. Pada dasarnya membangun bayangan biru sedikit gelap.

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

--surface-shadow-light tidak dibungkus dalam fungsi hsl. Hal ini karena nilai --shadow-strength akan digabungkan untuk membuat beberapa keburaman, dan CSS memerlukan bagian-bagian tersebut untuk melakukan penghitungan. Buka bagian shadow radial untuk mempelajari lebih lanjut.

Warna terang secara bersamaan

Anda tidak perlu mencari-cari untuk mengetahui cara membuat warna cahaya, karena semuanya ada di satu tempat dalam 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;
}
screenshot semua warna terang secara bersamaan
Sandbox di CodePen

Tema gelap

Sebagian besar brand tidak memulai dengan tema gelap, tetapi tema tersebut adalah varian dari tema utama mereka, yang biasanya lebih terang. Di sisi lain, pengguna sering memilih tema gelap untuk konteks yang berbeda, seperti malam hari. Faktor-faktor ini membuat saya mempertimbangkan dua hal terkait tema gelap:

  1. Pengguna umumnya akan berada dalam kegelapan saat menggunakan tema ini, jadi lakukan pengujian dalam kegelapan.
  2. Warna harus dikurangi saturasi agar tidak bergetar di layar karena terlalu intens.

pratinjau hasil akhir tema gelap

Merek

Tema terang menggunakan nilai 3 saluran warna hsl merek tanpa perubahan, tema gelap tidak. Saturasi dipotong setengah dan kecerahan dikurangi sebesar 50% relatif.

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

Warna teks

Dalam tema gelap, warna teks harus terang. Warna berikut memiliki nilai kecerahan yang tinggi, sehingga lebih mendekati warna putih.

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

Warna permukaan

Dalam tema gelap, warna permukaan harus gelap. Warna berikut memiliki kecerahan dan saturasi rendah, dengan permukaan ke-1 menjadi yang paling gelap pada 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%);
}

Bayangan

Dalam tema gelap, bayangan bisa sangat sulit dilihat. Masuk akal karena sulit untuk menggelapkan sesuatu yang sudah cukup gelap. Di sinilah --shadow-strength-dark menjadi sangat berguna karena memungkinkan kita menggelapkan bayangan dengan mengubah satu variabel.

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

Selain itu, lihat seberapa banyak saturasi dalam bayangan tersebut. Dapatkah Anda melihat warna saat Anda melihat antarmuka? Coba hapus saturasi dari devtools, mana yang Anda sukai?!

Semua warna gelap

* {
  --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;
}
screenshot semua warna gelap secara bersamaan
Sandbox di CodePen

Tema redup

Skema warna ini berfokus pada pengaturan cahaya dan saturasi. Harus ada saturasi yang cukup agar warna tetap terlihat, tetapi juga hanya sedikit melampaui skor kontras karena memang dimaksudkan agar redup dan memiliki kontras rendah.

pratinjau hasil akhir dari tema redup

Merek

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

Warna teks

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

Warna permukaan

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

Bayangan

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

Meredupkan semua warna

* {
  --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;
}
screenshot semua warna redup secara bersamaan
Sandbox di CodePen

Warna yang mudah diakses

Perhatikan bagaimana kecerahan terendah dalam set warna teks gelap adalah 65% dan kecerahan tertinggi dalam permukaan gelap adalah 25%. Itu adalah ruang kosong 40% kecerahan di antara keduanya. Dalam tema terang, ada ruang kosong 55% dalam tema terang. Mempertahankan perbedaan kecerahan antara warna teks dan permukaan sekitar 40-50% dapat membantu menjaga rasio kontras warna tetap tinggi, sekaligus menjadi penyesuaian halus jika skornya buruk.

Saya menyebutnya "bump bump til ya pass", yang merupakan interaksi menaikkan nilai kecerahan hingga alat menunjukkan bahwa saya lulus.

shift + panah bawah ditekan untuk menurunkan kecerahan dan meningkatkan kontras hingga lulus

Setiap tema yang dibuat dalam tantangan ini lulus skor kontras. Skema warna redup memiliki kontras terendah, tetapi masih memenuhi persyaratan minimum. Untuk membantu anggota tim lainnya menggunakan warna kontras yang baik, sebaiknya buat nama class yang memasangkan warna permukaan dengan warna teks yang mudah diakses.

.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);
}
Screenshot pasangan teks dan permukaan redup
Screenshot pasangan teks dan permukaan redup dengan VisBug

Rad Shadow

Tema menggunakan class utilitas yang disebut .rad-shadow. Bayangan ini dibuat dengan alat Smooth Shadow ini, yang sangat saya hargai. Saya mengambil cuplikan yang dihasilkan dan menyesuaikannya dengan warna dan perhitungan opasitas saya sendiri. Tujuannya adalah untuk membuat bayangan yang dapat disesuaikan dalam setiap skema warna.

setiap bayangan berdampingan

Untuk melakukannya, saya membuat 2 variabel untuk setiap skema warna yang akan disesuaikan, yaitu warna bayangan dan kekuatan bayangan. Warna digunakan untuk penyesuaian saturasi dan kegelapan, sedangkan kekuatan digunakan untuk cara mudah meningkatkan intensitas bayangan saat menggunakan skema warna gelap. Hasil akhirnya akan terlihat seperti ini.

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

Jika ingin menggunakan bayangan lebih lanjut dalam skema warna, saya akan menjadikan sudut bayangan sebagai konstanta token desain juga, karena arah cahaya harus sama di antara semua bayangan desain.

Penggunaan skema warna

Setelah warna ditentukan sebelumnya, saatnya mengubahnya menjadi properti agnostik skema. Maksud saya, sebagai penulis CSS di dalam project skema warna ini, seseorang jarang perlu mengakses nilai skema warna tertentu. Saya ingin mempermudah penggunaan tema.

Untuk melakukannya, penggunaan skema warna harus dilakukan secara eksklusif melalui properti kustom generik, yang akan kita tentukan sebentar lagi. Dengan cara ini, orang yang menggunakan variabel desain tidak perlu khawatir tentang skema warna mana yang saat ini ditetapkan, mereka hanya perlu menggunakan warna permukaan dan teks. Gunakan color: var(--text1), bukan color: var(--text1-light). Semua penyesuaian dan perubahan warna dilakukan pada tingkat yang jauh lebih tinggi di CSS.

Untuk memulai, gaya konektif tema terang dalam blok kode berikut, menghubungkan properti kustom generik dengan warna khusus tema terang. Sekarang semua penggunaan var(--brand) akan menggunakan warna merek terang.

Tema terang (otomatis)

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

Situs kini menggunakan tema terang. Ini adalah momen kesuksesan yang sangat menyenangkan. Mari kita nikmati beberapa momen lagi saat kita menggunakan warna standar dalam konteks skema warna lainnya.

Tema gelap (otomatis)

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

Tema terang

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

Tema gelap

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

Tema redup

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

Pada tahap ini, penulis bebas menggunakan generik skema warna yang disediakan sesuai kebutuhan, dan tidak perlu khawatir lagi tentang tema.

Kesimpulan

Sekarang setelah Anda tahu cara saya melakukannya, bagaimana Anda?! 🙂

Mari kita diversifikasi pendekatan kita dan pelajari semua cara untuk membangun di web. Buat Codepen atau hosting demo Anda sendiri, kirimkan tweet kepada saya, dan saya akan menambahkannya ke bagian Remix komunitas di bawah.

Sumber

Remix komunitas - @chris-kruining menambahkan penggeser warna, warna status, dan mode kontras untuk no-preference, more, dan less: demo.