Sintaksis warna relatif CSS

Membuat warna baru berdasarkan saluran dan nilai warna lain.

Adam Argyle
Adam Argyle

Di Chrome 119, terdapat fitur warna yang sangat canggih dari CSS Color Level 5. Sintaksis warna relatif membuat jalur yang lancar untuk manipulasi warna dalam CSS, yang menawarkan cara bagi penulis dan desainer untuk:

Sebelum sintaksis warna relatif, untuk mengubah opasitas warna, Anda perlu membuat properti kustom untuk saluran warna, biasanya HSL, dan menyusunnya menjadi warna akhir dan warna varian akhir. Artinya, Anda harus mengelola banyak bagian warna, yang dapat dengan cepat menjadi membebani.

:root {
  --brand-hue: 300deg;
  --brand-saturation: 75%;
  --brand-lightness: 50%;

  --brand-hsl:
    var(--brand-hue)
    var(--brand-saturation)
    var(--brand-lightness);

  --brand-color: hsl(var(--brand-hsl));

  /* all this work just so I can set the opacity to 50% in a variant */
  --brand-color-variant: hsl(var(--brand-hsl) / 50%);
}

Setelah sintaksis warna relatif, Anda dapat membuat warna merek dengan ruang warna atau sintaksis yang Anda butuhkan, dan membuat varian opasitas setengah dengan kode yang jauh lebih sedikit. Hal ini juga jauh lebih mudah untuk membaca intent gaya dan sistem.

:root {
  --brand-color: hsl(300deg 75% 50%);
  --brand-color-variant: hsl(from var(--brand-color) h s l / 50%);
}

Postingan ini akan membantu Anda mempelajari sintaksis dan mendemonstrasikan manipulasi warna umum.

Jika Anda lebih suka video, hampir semua artikel berikut dibahas dalam Tantangan GUI ini.

Ringkasan sintaksis

Tujuan sintaksis warna relatif adalah untuk memungkinkan derivasi warna dari warna lain. Warna dasar disebut warna asal, yaitu warna yang datang setelah kata kunci from baru. Browser akan mengonversi dan memisahkan warna asal ini serta menawarkan bagian-bagiannya sebagai variabel untuk digunakan dalam definisi warna baru.

Diagram sintaksis rgb(dari hijau r g b / alpha) ditampilkan, dengan panah meninggalkan bagian atas hijau dan melengkung ke awal rgb fungsi, panah ini terpecah menjadi 4 panah yang kemudian mengarah ke variabel yang relevan. 4
panah berwarna merah, hijau, biru, dan alfa. Merah dan biru memiliki nilai 0, hijau
adalah 128, dan alfa adalah 100%.

Diagram sebelumnya menunjukkan warna asal green yang dikonversi ke ruang warna warna baru, diubah menjadi angka individual yang direpresentasikan sebagai variabel r, g, b, dan alpha, yang kemudian langsung digunakan sebagai nilai warna rgb() baru.

Meskipun gambar ini menampilkan pengelompokan, proses, dan variabel, gambar ini juga tidak mengubah warna. Variabel dimasukkan kembali ke dalam warna yang tidak berubah, sehingga menghasilkan warna hijau.

Kata kunci from

Bagian pertama sintaksis yang harus dipelajari adalah bagian tambahan from <color> untuk menentukan warna. Ini terjadi tepat sebelum Anda menentukan nilai. Berikut adalah contoh kode dengan semua yang telah ditambahkan adalah from green, tepat sebelum nilai untuk rgb() ditentukan.

.syntax-introduction_same-colors {
  color: green;
  color: rgb(0 128 0);
  color: rgb(from green r g b);    /* result = rgb(0 128 0) */
}

Kata kunci from tersebut, jika dilihat sebagai parameter pertama dalam notasi fungsional, akan mengubah definisi warna menjadi warna relatif. Setelah kata kunci from, CSS menghendaki warna, warna yang akan menginspirasi warna berikutnya.

Konversi warna

Secara sederhana, fungsi ini mengonversi hijau ke saluran r g dan b untuk digunakan dalam warna baru.

rgb(from green r g b)           /* r=0 g=128 b=0 */
rgb(from rgb(0 128 0) r g b);   /* r=0 g=128 b=0 */

Warna dari properti kustom

Membaca rgb from green sangat jelas dan mudah dipahami. Itulah sebabnya properti kustom dan sintaksis warna relatif sangat cocok, karena Anda dapat menghilangkan misteri dari warna from. Anda juga umumnya tidak perlu mengetahui format warna warna properti kustom, karena Anda membuat warna baru dalam format pilihan Anda.

rgb(from rgb(255 105 180) r g b) /* ????? */
rgb(from var(--hotpink) r g b)   /* clear */

Bekerja di ruang warna pilihan Anda

Anda dapat memilih ruang warna dengan pilihan notasi warna fungsional.

rgb(from hsl(120 100% 25%) r g b)     /*  r=0   g=128  b=0    */
hsl(from hsl(120 100% 25%) h s l)     /*  h=120 s=100% l=25%  */
hwb(from hsl(120 100% 25%) h w b)     /*  h=120 w=0%   b=50%  */
lch(from hsl(120 100% 25%) l c h)     /*  l=46  c=68   h=134  */

Sintaksis warna relatif memiliki langkah konversi tersebut; warna setelah from dikonversi menjadi ruang warna seperti yang ditentukan di awal warna relatif. Input dan output tidak perlu cocok, yang sangat meringankan.

Kemampuan untuk memilih ruang warna juga bermanfaat, karena memilih ruang warna cenderung lebih berfokus pada jenis pergantian warna daripada preferensi. Preferensi ada dalam hasil, bukan format warna atau jenis saluran. Hal ini akan menjadi lebih jelas di bagian yang menunjukkan kasus penggunaan, karena ruang warna yang berbeda unggul dalam tugas yang berbeda.

Menggabungkan, mencocokkan, menghapus, dan mengulangi variabel

Ada hal aneh tetapi menarik tentang sintaksis ini, variabel tidak perlu diurutkan kembali dan dapat diulang.

rgb(from green g g g)    /* rgb(128 128 128) */
rgb(from green b r g)    /* rgb(0 0 128) */
rgb(from green 0 0 g)    /* rgb(0 0 128) */

Opasitas sebagai variabel

Sintaksis juga menyediakan opasitas sebagai variabel bernama alpha. Ini bersifat opsional, dan mengikuti / dalam notasi warna fungsional.

rgb(from #00800080 r g b / alpha)             /* alpha=50% */
rgb(from rgba(0,128,0,.5) r g b / alpha)      /* alpha=50% */
rgb(from rgb(0 128 0 / 50%) r g b / alpha)    /* alpha=50% */

Gunakan calc() atau fungsi CSS lainnya pada variabel

Sejauh ini, kita telah membuat warna hijau berulang kali. Mempelajari sintaksis, memahami langkah-langkah konversi dan destrukturisasi. Sekarang saatnya mengubah variabel, ubah output agar tidak sama dengan input.

green                              /*  h=120 s=100% l=25%  */
hsl(from green calc(h * 2) s l)    /*  h=240 s=100% l=25%  */

Sekarang warnanya biru tua. Hue digandakan, mengambil hue 120 dan mengubahnya menjadi 240, yang sepenuhnya mengubah warna. Tindakan ini memutar hue di sepanjang roda warna, sebuah trik rapi yang dibuat sangat sederhana dengan ruang warna silinder seperti HSL, HWB, LCH, dan OKLCH.

Untuk melihat nilai saluran secara visual, sehingga Anda bisa mendapatkan perhitungan yang tepat tanpa menebak atau menghafal spesifikasi, coba alat nilai saluran sintaksis warna relatif ini. Tindakan ini akan menampilkan setiap nilai saluran berdasarkan sintaksis yang Anda tentukan, sehingga Anda dapat mengetahui dengan tepat nilai yang tersedia untuk digunakan.

Memeriksa dukungan browser

@supports (color: rgb(from white r g b)) {
  /* safe to use relative color syntax */
}

Kasus penggunaan dan demonstrasi

Contoh dan kasus penggunaan berikut memiliki banyak sintaksis alternatif untuk mencapai hasil yang serupa atau sama. Variasi ini berasal dari ruang warna dan saluran yang ditawarkan.

Selain itu, banyak contoh akan menampilkan penyesuaian warna dengan kata-kata by dan to. by warna yang diubah adalah perubahan warna relatif; perubahan yang menggunakan nilai variabel dan membuat penyesuaian berdasarkan nilai saat ini. to yang diubah warnanya adalah perubahan warna mutlak; perubahan yang tidak menggunakan nilai variabel, tetapi menentukan nilai yang sama sekali baru.

Semua demo dapat ditemukan di koleksi Codepen ini.

Mencerahkan warna

Ruang warna OKLCH, OKLAB, XYZ, atau sRGB memberikan hasil yang paling dapat diprediksi saat mencerahkan warna.

Meringankan dengan jumlah

Contoh .lighten-by-25 berikut mengambil warna blue dan mengonversinya menjadi OKLCH, lalu mencerahkan warna biru dengan meningkatkan saluran l (kecerahan) dengan mengalikan nilai saat ini dengan 1.25. Tindakan ini akan mendorong kecerahan biru ke arah putih sebesar 25%.

.lighten-by-25 {
  background: oklch(from blue calc(l * 1.25) c h);
}

Mencerahkan ke nilai tertentu

Contoh .lighten-to-75 berikut tidak menggunakan saluran l untuk mempercerah blue, tetapi sepenuhnya mengganti nilai dengan 75%.

.lighten-to-75 {
  background: oklch(from blue 75% c h);
}

Menggelapkan warna

Ruang warna yang sama yang efektif untuk mencerahkan warna, juga bagus untuk menggelapkan warna.

Mempergelap dengan jumlah tertentu

Contoh .darken-by-25 berikut mengambil warna biru dan mengonversinya menjadi OKLCH, lalu menggelapkan warna biru dengan mengurangi saluran l (kecerahan) sebesar 25% dengan menggandakan nilai dengan .75. Hal ini mendorong warna biru ke arah hitam sebesar 25%.

.darken-by-25 {
  background: oklch(from blue calc(l * .75) c h);
}

Mempergelap ke nilai yang ditentukan

Contoh .darken-to-25 berikut tidak menggunakan saluran l untuk menggelapkan blue, tetapi sepenuhnya mengganti nilai dengan 25%.

.darken-to-25 {
  background: oklch(from blue 25% c h);
}

Menyaturasi warna

Menjenuhkan menurut jumlah

Contoh .saturate-by-50 berikut menggunakan s dari hsl() untuk meningkatkan vibrasi orchid dengan 50% relatif.

.saturate-by-50 {
  background: hsl(from orchid h calc(s * 1.5) l);
}

Mencapai jumlah tertentu

Contoh .saturate-to-100 berikut tidak menggunakan saluran s dari hsl(), tetapi menentukan nilai saturasi yang diinginkan. Dalam contoh ini, saturasi dinaikkan ke 100%.

.saturate-to-100 {
  background: hsl(from orchid h 100% l);
}

Mengurangi saturasi warna

Mengurangi saturasi dengan jumlah tertentu

Contoh .desaturate-by-half berikut menggunakan s dari hsl() untuk mengurangi saturasi indigo sebanyak setengah.

.desaturate-by-half {
  background: hsl(from indigo h calc(s / 2) l);
}

Mengurangi saturasi ke nilai tertentu

Daripada mendesaturasi dengan jumlah tertentu, Anda dapat mendesaturasi ke nilai tertentu yang diinginkan. Contoh .desaturate-to-25 berikut membuat warna baru berdasarkan indigo, tetapi menetapkan saturasi ke 25%.

.desaturate-to-25 {
  background: hsl(from indigo h 25% l);
}

Meningkatkan kroma warna

Efek ini mirip dengan menjenuhkan warna, tetapi berbeda dalam beberapa cara. Pertama, ini adalah perubahan chroma, bukan perubahan saturation, dan ini karena ruang warna yang dapat meningkatkan rentang dinamis tinggi tidak menggunakan saturasi. Ruang warna yang menampilkan chroma memiliki kemampuan rentang dinamis tinggi, sehingga penulis dapat meningkatkan vibrasi warna lebih jauh daripada saturasi yang mampu.

.increase-chroma {
  background: oklch(from orange l calc(c + .1) h);
}

Menyesuaikan opasitas warna

Membuat varian warna semi-transparan adalah salah satu penyesuaian warna yang paling umum dilakukan dalam sistem desain. Lihat contoh di pengantar artikel ini jika Anda melewatkan bagian tersebut, contoh ini menguraikan ruang masalah dengan sangat baik.

Menyesuaikan opasitas dengan jumlah tertentu

.decrease-opacity-by-25 {
  background: rgb(from lime r g b / calc(alpha / 2));
}

Menyesuaikan opasitas ke nilai tertentu

.decrease-opacity-to-25 {
  background: rgb(from lime r g b / 25%);
}

Membalik warna

Inversi warna adalah fungsi penyesuaian warna umum yang ditemukan di library warna. Salah satu cara untuk melakukannya adalah dengan mengonversi warna ke RGB, lalu mengurangi setiap nilai saluran dari 1.

.invert-each-rgb-channel {
  background: rgb(from yellow calc(255 - r) calc(255 - g) calc(255 - b));
}

Melengkapi warna

Jika sasaran Anda bukan untuk membalik warna, tetapi melengkapinya, rotasi hue mungkin yang Anda cari. Pilih ruang warna yang menawarkan hue sebagai sudut, lalu gunakan calc() untuk memutar hue dengan jumlah yang Anda inginkan. Menemukan pelengkap warna dilakukan dengan memutar setengah putaran, dalam hal ini Anda dapat menambahkan atau mengurangi dari saluran h dengan 180 untuk mendapatkan hasilnya.

.complementary-color {
  background: hsl(from blue calc(h + 180) s l);
}

Membuat kontras warna

Sebagai metode untuk mencapai rasio kontras warna yang dapat diakses, pertimbangkan L&midast; (Lstar). Ini menggunakan saluran kecerahan (L) yang (kira-kira) seragam secara persepsi dari LCH dan OKLCH, dalam calc(). Bergantung pada apakah Anda menargetkan kontras rendah, sedang, atau tinggi, delta L&midast; adalah sekitar ~40, ~50, atau ~60.

Teknik ini berfungsi dengan baik di semua hue dalam LCH atau OKLCH.

Membuat kontras warna yang lebih gelap

Class .well-contrasting-darker-color menunjukkan L* dengan delta 60. Karena warna asalnya adalah warna gelap (kecerahan nilai rendah), 60% (.6) ditambahkan ke saluran kecerahan. Teknik ini digunakan untuk menemukan warna teks gelap yang kontras, hue yang sama, dan latar belakang terang.

.well-contrasting-darker-color {
  background: darkred;
  color: oklch(from darkred calc(l + .60) c h);
}

Membuat kontras warna yang lebih terang

Class .well-contrasting-lighter-color juga menunjukkan L* dengan delta 60%. Karena warna asalnya adalah warna terang (kecerahan nilai tinggi), .60 dikurangi dari saluran kecerahan.

.well-contrasting-lighter-color {
  background: lightpink;
  color: oklch(from lightpink calc(l - .60) c h);
}

Palet warna

Sintaksis warna relatif sangat baik dalam membuat palet warna. Hal ini sangat berguna dan efektif karena jumlah ruang warna yang tersedia. Semua contoh berikut menggunakan OKLCH karena saluran kecerahan dapat diandalkan dan saluran hue dapat diputar tanpa efek samping. Contoh terakhir menunjukkan kombinasi penyesuaian rotasi kecerahan dan hue untuk hasil yang lebih menarik.

Buka contoh kode sumber untuk ini dan coba ubah --base-color, untuk melihat seberapa dinamis palet ini. Seru!

Jika Anda suka video, saya memberikan informasi mendalam tentang membuat palet warna di CSS dengan OKLCH di YouTube.

Palet monokromatik

Membuat palet monokromatik adalah membuat palet dari hue yang sama, tetapi dengan variasi kecerahan dan kegelapan. Warna tengah adalah warna sumber untuk palet, dengan dua varian yang lebih terang dan dua varian yang lebih gelap ditempatkan di kedua sisi.

:root {
  --base-color: deeppink;

  --color-0: oklch(from var(--base-color) calc(l + .20) c h); /* lightest */
  --color-1: oklch(from var(--base-color) calc(l + .10) c h);
  --color-2: var(--base-color);
  --color-3: oklch(from var(--base-color) calc(l - .10) c h);
  --color-4: oklch(from var(--base-color) calc(l - .20) c h); /* darkest */
}
Mencoba banyak palet yang dibuat dengan sintaksis warna relatif dan OKLCH

Open Props, library variabel CSS gratis, menawarkan palet warna yang dibuat dengan strategi ini dan membuatnya mudah digunakan dengan impor. Semuanya juga dibuat dari warna yang dapat Anda sesuaikan, Anda hanya perlu memberikan warna dan palet akan muncul.

Palet analog

Karena rotasi hue sangat mudah dengan OKLCH dan HSL, membuat palet warna analog menjadi mudah. Putar hue dengan jumlah yang Anda sukai dan ubah warna dasarnya, lalu lihat palet baru yang dibuat oleh browser.

:root {
  --base-color: blue;

  --primary:   var(--base-color);
  --secondary: oklch(from var(--base-color) l c calc(h - 45));
  --tertiary:  oklch(from var(--base-color) l c calc(h + 45));
}

Palet triad

Serupa dengan warna pelengkap, palet warna triadik adalah rotasi hue yang berlawanan tetapi harmonis dengan warna dasar. Jika warna pelengkap berada di sisi yang berlawanan dari suatu warna, seperti garis lurus yang digambar melalui bagian tengah roda warna, palet triadik seperti segitiga garis, yang menemukan 2 warna yang diputar secara merata dari warna dasar. Lakukan hal ini dengan memutar hue 120deg.

Ini adalah sedikit penyederhanaan teori warna, tetapi cukup untuk memulai Anda ke palet triadik yang lebih kompleks jika Anda tertarik.

:root {
  --base-color: yellow;
  --triad-1: oklch(from var(--base-color) l c calc(h - 120));
  --triad-2: oklch(from var(--base-color) l c calc(h + 120));
}

Palet tetradik

Palet tetradik adalah empat warna yang dibagi secara merata di sekitar roda warna, sehingga membuat palet tanpa nilai dominan yang jelas. Anda juga dapat menganggapnya seperti dua pasang warna komplementer. Jika digunakan dengan bijak, data ini dapat sangat bermakna.

Ini adalah sedikit penyederhanaan teori warna, tetapi cukup untuk memulai palet tetradik yang lebih kompleks jika Anda tertarik.

:root {
  --base-color: lime;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) l c calc(h + 90));
  --color-3: oklch(from var(--base-color) l c calc(h + 180));
  --color-4: oklch(from var(--base-color) l c calc(h + 270));
}

Monokromatik dengan sedikit rotasi hue

Banyak pakar warna yang menyimpan trik ini. Masalahnya, skala warna monokromatik bisa jadi cukup membosankan. Solusinya adalah menambahkan rotasi hue minor atau mayor ke setiap warna baru saat kecerahan diubah.

Contoh berikut mengurangi kecerahan sebesar 10% untuk setiap pilihan warna dan juga memutar hue sebesar 10 derajat. Hasilnya, palet hotpink hingga indigo yang tampaknya tercampur dengan lancar seperti gradien.

:root {
  --base-color: deeppink;

  --color-1: var(--base-color);
  --color-2: oklch(from var(--base-color) calc(l - .10) c calc(h - 10));
  --color-3: oklch(from var(--base-color) calc(l - .20) c calc(h - 20));
  --color-4: oklch(from var(--base-color) calc(l - .30) c calc(h - 30));
  --color-5: oklch(from var(--base-color) calc(l - .40) c calc(h - 40));
}
Coba papan peringkat ini yang dibuat dengan OKLCH dan rotasi hue

Antarmuka papan peringkat berikut menggunakan strategi rotasi hue ini. Setiap item daftar melacak indeksnya dalam dokumen sebagai variabel yang disebut --i. Indeks ini kemudian digunakan untuk menyesuaikan kromatik, kecerahan, dan hue. Penyesuaian hanya sebesar 5% atau 5 derajat, jauh lebih halus daripada contoh di atas dengan deeppink, sehingga perlu ketelitian untuk melihat alasan papan peringkat ini dapat memiliki warna apa pun dengan keanggunan tersebut.

Pastikan untuk mengubah hue di penggeser di bawah papan peringkat, dan lihat sintaksis warna relatif yang menciptakan momen warna yang indah.

li {
  --_bg: oklch(
    /* decrease lightness as list grows */
    calc(75% - (var(--i) * 5%))

    /* decrease chroma as list grows */
    calc(.2 - (var(--i) * .01))

    /* lightly rotate the hue as the list grows */
    calc(var(--hue) - (var(--i) + 5))
  );
}