Panduan Strategi Untuk Properti Kustom CSS
Diterbitkan: 2022-03-10Properti Kustom CSS (terkadang dikenal sebagai 'variabel CSS') kini didukung di semua browser modern, dan orang-orang mulai menggunakannya dalam produksi. Ini bagus, tetapi mereka berbeda dari variabel di praprosesor, dan saya telah melihat banyak contoh orang yang menggunakannya tanpa mempertimbangkan keuntungan apa yang mereka tawarkan.
Properti kustom memiliki potensi besar untuk mengubah cara kita menulis dan menyusun CSS dan pada tingkat yang lebih rendah, cara kita menggunakan JavaScript untuk berinteraksi dengan komponen UI. Saya tidak akan fokus pada sintaks dan cara kerjanya (untuk itu saya sarankan Anda membaca "Saatnya Mulai Menggunakan Properti Kustom"). Sebaliknya, saya ingin melihat lebih dalam strategi untuk mendapatkan hasil maksimal dari CSS Custom Properties.
Bagaimana Mereka Mirip Dengan Variabel Dalam Preprosesor?
Properti Kustom sedikit mirip dengan variabel di praprosesor tetapi memiliki beberapa perbedaan penting. Perbedaan pertama dan paling jelas adalah sintaks.
Dengan SCSS
kami menggunakan simbol dolar untuk menunjukkan variabel:
$smashing-red: #d33a2c;
Dalam Less kami menggunakan simbol @
:
@smashing-red: #d33a2c;
Properti khusus mengikuti konvensi serupa dan menggunakan awalan --
:
:root { --smashing-red: #d33a2c; } .smashing-text { color: var(--smashing-red); }
Satu perbedaan penting antara properti kustom dan variabel di praprosesor adalah bahwa properti kustom memiliki sintaks yang berbeda untuk menetapkan nilai dan mengambil nilai itu. Saat mengambil nilai properti khusus, kami menggunakan fungsi var()
.
Perbedaan paling jelas berikutnya adalah pada nama. Mereka disebut 'properti khusus' karena mereka benar-benar properti CSS. Di praprosesor, Anda dapat mendeklarasikan dan menggunakan variabel hampir di mana saja, termasuk blok deklarasi luar, dalam aturan media, atau bahkan sebagai bagian dari pemilih.
$breakpoint: 800px; $smashing-red: #d33a2c; $smashing-things: ".smashing-text, .cats"; @media screen and (min-width: $breakpoint) { #{$smashing-things} { color: $smashing-red; } }
Sebagian besar contoh di atas tidak valid menggunakan properti khusus.
Properti khusus memiliki aturan yang sama tentang di mana mereka dapat digunakan sebagai properti CSS normal. Jauh lebih baik untuk menganggapnya sebagai properti dinamis daripada variabel. Itu berarti mereka hanya dapat digunakan di dalam blok deklarasi, atau dengan kata lain, properti khusus diikat ke pemilih. Ini bisa berupa pemilih :root
, atau pemilih valid lainnya.
:root { --smashing-red: #d33a2c; } @media screen and (min-width: 800px) { .smashing-text, .cats { --margin-left: 1em; } }
Anda dapat mengambil nilai properti kustom di mana pun Anda akan menggunakan nilai dalam deklarasi properti. Ini berarti mereka dapat digunakan sebagai nilai tunggal, sebagai bagian dari pernyataan singkat atau bahkan di dalam persamaan calc()
.
.smashing-text, .cats { color: var(--smashing-red); margin: 0 var(--margin-horizontal); padding: calc(var(--margin-horizontal) / 2) }
Namun, mereka tidak dapat digunakan dalam kueri media, atau pemilih termasuk :nth-child()
.
Mungkin ada lebih banyak lagi yang ingin Anda ketahui tentang sintaks dan cara kerja properti kustom, seperti cara menggunakan nilai fallback dan dapatkah Anda menetapkan variabel ke variabel lain (ya), tetapi pengenalan dasar ini seharusnya cukup untuk memahami sisanya konsep dalam artikel ini. Untuk informasi lebih lanjut tentang spesifik cara kerja properti kustom, Anda dapat membaca "Saatnya Mulai Menggunakan Properti Kustom" yang ditulis oleh Serg Hospodarets.
Dinamis vs. Statis
Selain perbedaan kosmetik, perbedaan paling signifikan antara variabel dalam praprosesor dan properti khusus adalah bagaimana cakupannya. Kita dapat merujuk ke variabel sebagai cakupan statis atau dinamis. Variabel dalam praprosesor bersifat statis, sedangkan properti kustom bersifat dinamis.
Dalam hal CSS, statis berarti Anda dapat memperbarui nilai variabel pada titik yang berbeda dalam proses kompilasi, tetapi ini tidak dapat mengubah nilai kode yang datang sebelumnya.
$background: blue; .blue { background: $background; } $background: red; .red { background: $background; }
menghasilkan:
.blue { background: blue; } .red { background: red; }
Setelah ini dirender ke CSS, variabelnya hilang. Ini berarti bahwa kita berpotensi membaca file .scss
dan menentukan outputnya tanpa mengetahui apa pun tentang HTML, browser, atau input lainnya. Ini tidak terjadi dengan properti kustom.
Praprosesor memang memiliki semacam "cakupan blok" di mana variabel dapat diubah sementara di dalam pemilih, fungsi, atau mixin. Ini mengubah nilai variabel di dalam blok, tetapi masih statis. Ini terkait dengan blok, bukan pemilih. Pada contoh di bawah, variabel $background
diubah di dalam blok .example
. Itu berubah kembali ke nilai awal di luar blok, bahkan jika kita menggunakan pemilih yang sama.
$background: red; .example { $background: blue; background: $background; } .example { background: $background; }
Ini akan mengakibatkan:
.example { background: blue; } .example { background: red; }
Properti kustom bekerja secara berbeda. Jika menyangkut properti kustom, cakupan dinamis berarti properti tersebut tunduk pada pewarisan dan kaskade. Properti terikat ke pemilih dan jika nilainya berubah, ini memengaruhi semua elemen DOM yang cocok seperti properti CSS lainnya.
Ini bagus karena Anda dapat mengubah nilai properti khusus di dalam kueri media, dengan pemilih semu seperti mengarahkan kursor, atau bahkan dengan JavaScript.
a { --link-color: black; } a:hover, a:focus { --link-color: tomato; } @media screen and (min-width: 600px) { a { --link-color: blue; } } a { color: var(--link-color); }
Kami tidak perlu mengubah tempat properti kustom digunakan — kami mengubah nilai properti kustom dengan CSS. Ini berarti dengan menggunakan properti khusus yang sama, kita dapat memiliki nilai yang berbeda di tempat atau konteks yang berbeda pada halaman yang sama.
Global vs. Lokal
Selain statis atau dinamis, variabel juga bisa bersifat global atau lokal. Jika Anda menulis JavaScript, Anda akan terbiasa dengan ini. Variabel dapat diterapkan ke segala sesuatu di dalam aplikasi, atau cakupannya dapat dibatasi pada fungsi atau blok kode tertentu.
CSSnya mirip. Kami memiliki beberapa hal yang diterapkan secara global dan beberapa hal yang lebih lokal. Warna merek, spasi vertikal, dan tipografi adalah contoh hal-hal yang mungkin ingin Anda terapkan secara global dan konsisten di seluruh situs web atau aplikasi Anda. Kami juga memiliki barang-barang lokal. Misalnya, komponen tombol mungkin memiliki varian kecil dan besar. Anda tidak ingin ukuran dari tombol ini diterapkan ke semua elemen input atau bahkan setiap elemen di halaman.
Ini adalah sesuatu yang kita kenal di CSS. Kami telah mengembangkan sistem desain, konvensi penamaan, dan pustaka JavaScript, semuanya untuk membantu mengisolasi komponen lokal dan elemen desain global. Properti kustom memberikan opsi baru untuk menangani masalah lama ini.
Properti Kustom CSS secara default dicakup secara lokal ke pemilih tertentu tempat kami menerapkannya. Jadi mereka agak seperti variabel lokal. Namun, properti kustom juga diwariskan, sehingga dalam banyak situasi, properti tersebut berperilaku seperti variabel global — terutama bila diterapkan ke pemilih :root
. Ini berarti bahwa kita perlu memikirkan cara menggunakannya.
Begitu banyak contoh yang menunjukkan properti kustom diterapkan ke elemen :root
dan meskipun, ini bagus untuk demo, ini dapat mengakibatkan cakupan global yang berantakan dan masalah pewarisan yang tidak diinginkan. Untungnya, kita telah mempelajari pelajaran ini.
Variabel Global Cenderung Statis
Ada beberapa pengecualian kecil, tetapi secara umum, sebagian besar hal global dalam CSS juga statis.
Variabel global seperti warna merek, tipografi, dan spasi cenderung tidak banyak berubah dari satu komponen ke komponen berikutnya. Ketika mereka berubah, ini cenderung menjadi rebranding global atau beberapa perubahan signifikan lainnya yang jarang terjadi pada produk yang matang. Masih masuk akal untuk hal-hal ini menjadi variabel, mereka digunakan di banyak tempat, dan variabel membantu dengan konsistensi. Tetapi tidak masuk akal bagi mereka untuk menjadi dinamis. Nilai variabel ini tidak berubah secara dinamis.
Untuk alasan ini, saya sangat menyarankan menggunakan preprocessors untuk variabel global (statis). Ini tidak hanya memastikan bahwa mereka selalu statis, tetapi secara visual menunjukkan mereka di dalam kode. Ini dapat membuat CSS jauh lebih mudah dibaca dan lebih mudah dirawat.
Variabel Statis Lokal OK (Terkadang)
Anda mungkin berpikir mengingat pendirian yang kuat pada variabel global yang statis, bahwa dengan refleksi, semua variabel lokal mungkin perlu dinamis. Meskipun benar bahwa variabel lokal memang cenderung dinamis, ini tidak sekuat kecenderungan variabel global untuk menjadi statis.
Variabel statis lokal sangat baik dalam banyak situasi. Saya menggunakan variabel preprocessors dalam file komponen sebagian besar sebagai kenyamanan pengembang.
Pertimbangkan contoh klasik dari komponen tombol dengan beberapa variasi ukuran.
scss
saya mungkin terlihat seperti ini:
$button-sml: 1em; $button-med: 1.5em; $button-lrg: 2em; .btn { // Visual styles } .btn-sml { font-size: $button-sml; } .btn-med { font-size: $button-med; } .btn-lrg { font-size: $button-lrg; }
Jelas, contoh ini akan lebih masuk akal jika saya menggunakan variabel beberapa kali atau menurunkan nilai margin dan padding dari variabel ukuran. Namun, kemampuan untuk membuat prototipe ukuran yang berbeda dengan cepat mungkin menjadi alasan yang cukup.
Karena sebagian besar variabel statis bersifat global, saya suka membedakan variabel statis yang hanya digunakan di dalam komponen. Untuk melakukan ini, Anda dapat mengawali variabel ini dengan nama komponen, atau Anda dapat menggunakan awalan lain seperti c-variable-name
untuk komponen atau l-variable-name
untuk lokal. Anda dapat menggunakan awalan apa pun yang Anda inginkan, atau Anda dapat menggunakan awalan variabel global. Apa pun yang Anda pilih, akan sangat membantu untuk membedakan terutama jika mengonversi basis kode yang ada untuk menggunakan properti khusus.
Kapan Menggunakan Properti Kustom
Jika boleh menggunakan variabel statis di dalam komponen, kapan kita harus menggunakan properti khusus? Mengonversi variabel praprosesor yang ada ke properti khusus biasanya tidak masuk akal. Lagi pula, alasan untuk properti khusus sangat berbeda. Properti kustom masuk akal saat kita memiliki properti CSS yang berubah relatif terhadap kondisi di DOM — terutama kondisi dinamis seperti :focus
, :hover
, kueri media, atau dengan JavaScript.
Saya menduga kami akan selalu menggunakan beberapa bentuk variabel statis, meskipun kami mungkin membutuhkan lebih sedikit di masa mendatang, karena properti khusus menawarkan cara baru untuk mengatur logika dan kode. Sampai saat itu, saya pikir dalam kebanyakan situasi kita akan bekerja dengan kombinasi variabel preprocessor dan properti kustom.
Sangat membantu untuk mengetahui bahwa kita dapat menetapkan variabel statis ke properti khusus. Baik itu global atau lokal, masuk akal dalam banyak situasi untuk mengonversi variabel statis, menjadi properti kustom dinamis lokal.
Catatan : Tahukah Anda bahwa $var
adalah nilai yang valid untuk properti khusus? Versi terbaru Sass mengenali hal ini, dan oleh karena itu kita perlu menginterpolasi variabel yang ditetapkan ke properti khusus, seperti ini: #{$var}
. Ini memberi tahu Sass bahwa Anda ingin menampilkan nilai variabel, bukan hanya $var
di stylesheet. Ini hanya diperlukan untuk situasi seperti properti khusus, di mana nama variabel juga bisa menjadi CSS yang valid.
Jika kita mengambil contoh tombol di atas dan memutuskan semua tombol harus menggunakan variasi kecil pada perangkat seluler, terlepas dari kelas yang diterapkan dalam HTML, sekarang situasinya lebih dinamis. Untuk ini, kita harus menggunakan properti khusus.
$button-sml: 1em; $button-med: 1.5em; $button-lrg: 2em; .btn { --button-size: #{$button-sml}; } @media screen and (min-width: 600px) { .btn-med { --button-size: #{$button-med}; } .btn-lrg { --button-size: #{$button-lrg}; } } .btn { font-size: var(--button-size); }
Di sini saya membuat satu properti khusus: --button-size
. Properti kustom ini awalnya dicakup untuk semua elemen tombol menggunakan kelas btn
. Saya kemudian mengubah nilai --button-size
di atas 600px untuk kelas btn-med
dan btn-lrg
. Terakhir, saya menerapkan properti khusus ini ke semua elemen tombol di satu tempat.
Jangan Terlalu Pintar
Sifat dinamis dari properti kustom memungkinkan kita untuk membuat beberapa komponen yang cerdas dan rumit.
Dengan diperkenalkannya praprosesor, banyak dari kita membuat perpustakaan dengan abstraksi yang cerdas menggunakan mixin dan fungsi khusus. Dalam kasus terbatas, contoh seperti ini masih berguna hingga saat ini, tetapi sebagian besar, semakin lama saya bekerja dengan praprosesor, semakin sedikit fitur yang saya gunakan. Hari ini, saya menggunakan preprocessors hampir secara eksklusif untuk variabel statis.
Properti khusus tidak akan (dan tidak boleh) kebal dari jenis eksperimen ini, dan saya berharap dapat melihat banyak contoh cerdas. Tetapi dalam jangka panjang, kode yang dapat dibaca dan dipelihara akan selalu memenangkan abstraksi yang cerdas (setidaknya dalam produksi).
Saya membaca artikel yang sangat bagus tentang topik ini di Media Kamp Kode Gratis baru-baru ini. Itu ditulis oleh Bill Sourour dan disebut "Jangan Lakukan Saat Runtime. Lakukan Pada Waktu Desain.” Daripada memparafrasekan argumennya, saya akan membiarkan Anda membacanya.
Satu perbedaan utama antara variabel praprosesor dan properti kustom adalah bahwa properti kustom bekerja saat runtime. Ini berarti hal-hal yang mungkin dapat diterima, dalam hal kompleksitas, dengan praprosesor mungkin bukan ide yang baik dengan properti khusus.
Salah satu contoh yang menggambarkan ini untuk saya baru-baru ini adalah ini:
:root { --font-scale: 1.2; --font-size-1: calc(var(--font-scale) * var(--font-size-2)); --font-size-2: calc(var(--font-scale) * var(--font-size-3)); --font-size-3: calc(var(--font-scale) * var(--font-size-4)); --font-size-4: 1rem; }
Ini menghasilkan skala modular. Skala modular adalah serangkaian angka yang berhubungan satu sama lain menggunakan rasio. Mereka sering digunakan dalam desain dan pengembangan web untuk mengatur ukuran font atau spasi.
Dalam contoh ini, setiap properti kustom ditentukan menggunakan calc()
, dengan mengambil nilai properti kustom sebelumnya dan mengalikannya dengan rasio. Melakukan ini, kita bisa mendapatkan nomor berikutnya dalam skala.
Ini berarti rasio dihitung saat run-time dan Anda dapat mengubahnya dengan hanya memperbarui nilai properti --font-scale
. Sebagai contoh:
@media screen and (min-width: 800px) { :root { --font-scale: 1.33; } }
Ini pintar, ringkas, dan jauh lebih cepat daripada menghitung semua nilai lagi jika Anda ingin mengubah skala. Itu juga sesuatu yang tidak akan saya lakukan dalam kode produksi.
Meskipun contoh di atas berguna untuk membuat prototipe, dalam produksi, saya lebih suka melihat sesuatu seperti ini:
:root { --font-size-1: 1.728rem; --font-size-2: 1.44rem; --font-size-3: 1.2em; --font-size-4: 1em; } @media screen and (min-width: 800px) { :root { --font-size-1: 2.369rem; --font-size-2: 1.777rem; --font-size-3: 1.333rem; --font-size-4: 1rem; } }
Mirip dengan contoh di artikel Bill, saya merasa terbantu untuk melihat apa nilai sebenarnya. Kami membaca kode lebih sering daripada yang kami tulis dan nilai global seperti skala font jarang berubah dalam produksi.
Contoh di atas masih belum sempurna. Itu melanggar aturan sebelumnya bahwa nilai global harus statis . Saya lebih suka menggunakan variabel praprosesor dan mengonversinya menjadi properti kustom dinamis lokal menggunakan teknik yang ditunjukkan sebelumnya.
Penting juga untuk menghindari situasi di mana kita beralih dari menggunakan satu properti kustom ke properti kustom yang berbeda. Ini bisa terjadi ketika kita memberi nama properti seperti ini.
Ubah Nilainya Bukan Variabelnya
Mengubah nilai bukan variabel adalah salah satu strategi terpenting untuk menggunakan properti khusus secara efektif.
Sebagai aturan umum, Anda tidak boleh mengubah properti khusus mana yang digunakan untuk satu tujuan. Ini mudah dilakukan karena inilah tepatnya cara kami melakukan berbagai hal dengan praprosesor, tetapi tidak masuk akal dengan properti khusus.
Dalam contoh ini, kami memiliki dua properti kustom yang digunakan pada komponen contoh. Saya beralih dari menggunakan nilai --font-size-small
ke --font-size-large
tergantung pada ukuran layar.
:root { --font-size-small: 1.2em; --font-size-large: 2em; } .example { font-size: var(--font-size-small); } @media screen and (min-width: 800px) { .example { font-size: var(--font-size-large); } }
Cara yang lebih baik untuk melakukan ini adalah dengan mendefinisikan satu properti khusus yang dicakup ke komponen. Kemudian menggunakan kueri media, atau pemilih lainnya, ubah nilainya.
.example { --example-font-size: 1.2em; } @media screen and (min-width: 800px) { .example { --example-font-size: 2em; } }
Akhirnya, di satu tempat, saya menggunakan nilai properti khusus ini:
.example { font-size: var(--example-font-size); }
Dalam contoh ini dan contoh lainnya sebelumnya, kueri media hanya digunakan untuk mengubah nilai properti kustom. Anda mungkin juga memperhatikan bahwa hanya ada satu tempat di mana pernyataan var()
digunakan, dan properti CSS biasa diperbarui.
Pemisahan antara deklarasi variabel dan deklarasi properti ini disengaja. Ada banyak alasan untuk ini, tetapi manfaatnya paling jelas ketika memikirkan desain responsif.
Desain Responsif Dengan Properti Kustom
Salah satu kesulitan dengan desain responsif ketika sangat bergantung pada kueri media adalah bahwa tidak peduli bagaimana Anda mengatur CSS Anda, gaya yang berkaitan dengan komponen tertentu menjadi terfragmentasi di seluruh lembar gaya.
Sangat sulit untuk mengetahui properti CSS apa yang akan diubah. Namun, Properti Kustom CSS dapat membantu kami mengatur beberapa logika yang terkait dengan desain responsif dan membuat bekerja dengan kueri media menjadi jauh lebih mudah.
Jika Berubah, Itu Variabel
Properti yang berubah menggunakan kueri media secara inheren dinamis dan properti kustom menyediakan sarana untuk mengekspresikan nilai dinamis dalam CSS. Ini berarti bahwa jika Anda menggunakan kueri media untuk mengubah properti CSS apa pun, Anda harus menempatkan nilai ini di properti khusus.
Anda kemudian dapat memindahkan ini, bersama dengan semua aturan media, status hover, atau pemilih dinamis apa pun yang menentukan bagaimana nilai berubah, ke bagian atas dokumen.
Pisahkan Logika Dari Desain
Jika dilakukan dengan benar, pemisahan logika dan desain berarti kueri media hanya digunakan untuk mengubah nilai properti kustom . Ini berarti semua logika yang terkait dengan desain responsif harus berada di bagian atas dokumen, dan di mana pun kita melihat pernyataan var()
di CSS kita, kita segera tahu bahwa properti ini yang berubah. Dengan metode penulisan CSS tradisional, tidak ada cara untuk mengetahui hal ini secara sekilas.
Banyak dari kita menjadi sangat baik dalam membaca dan menafsirkan CSS secara sekilas sambil melacak di kepala kita properti mana yang berubah dalam situasi yang berbeda. Saya bosan dengan ini, dan saya tidak ingin melakukan ini lagi! Properti khusus sekarang menyediakan tautan antara logika dan implementasinya, jadi kita tidak perlu melacak ini, dan itu sangat berguna!
Lipatan Logika
Ide mendeklarasikan variabel di bagian atas dokumen atau fungsi bukanlah ide baru. Ini adalah sesuatu yang kami lakukan di sebagian besar bahasa, dan sekarang ini juga dapat kami lakukan di CSS. Menulis CSS dengan cara ini menciptakan perbedaan visual yang jelas antara CSS di bagian atas dokumen dan di bawahnya. Saya perlu cara untuk membedakan bagian-bagian ini ketika saya membicarakannya dan gagasan "lipatan logika" adalah metafora yang mulai saya gunakan.
Paro atas berisi semua variabel praprosesor dan properti khusus. Ini mencakup semua nilai berbeda yang dapat dimiliki properti khusus. Seharusnya mudah untuk melacak bagaimana properti kustom berubah.
CSS di paro bawah sangat sederhana dan sangat deklaratif serta mudah dibaca. Rasanya seperti CSS sebelum kueri media dan kerumitan lain yang diperlukan dari CSS modern.
Lihatlah contoh yang sangat sederhana dari sistem grid flexbox enam kolom:
.row { --row-display: block; } @media screen and (min-width: 600px) { .row { --row-display: flex; } }
Properti kustom --row-display
awalnya disetel untuk block
. Di atas 600px mode tampilan diatur ke flex.
Paro bawah mungkin terlihat seperti ini:
.row { display: var(--row-display); flex-direction: row; flex-wrap: nowrap; } .col-1, .col-2, .col-3, .col-4, .col-5, .col-6 { flex-grow: 0; flex-shrink: 0; } .col-1 { flex-basis: 16.66%; } .col-2 { flex-basis: 33.33%; } .col-3 { flex-basis: 50%; } .col-4 { flex-basis: 66.66%; } .col-5 { flex-basis: 83.33%; } .col-6 { flex-basis: 100%; }
Kami segera tahu --row-display
adalah nilai yang berubah. Awalnya, itu akan menjadi block
, sehingga nilai flex akan diabaikan.
Contoh ini cukup sederhana, tetapi jika kami memperluasnya untuk menyertakan kolom lebar fleksibel yang mengisi ruang yang tersisa, kemungkinan nilai flex-grow
, flex-shrink
dan flex-basis
perlu dikonversi ke properti kustom. Anda dapat mencoba ini atau melihat contoh yang lebih rinci di sini.
Properti Kustom Untuk Tema
Saya sebagian besar menentang penggunaan properti khusus untuk variabel dinamis global dan mudah-mudahan menyiratkan bahwa melampirkan properti khusus ke pemilih :root
dalam banyak kasus dianggap berbahaya. Tetapi setiap aturan memiliki pengecualian, dan untuk properti khusus, itu bertema.
Penggunaan properti kustom global secara terbatas dapat membuat tema menjadi jauh lebih mudah.
Tema umumnya mengacu pada membiarkan pengguna menyesuaikan UI dalam beberapa cara. Ini bisa berupa perubahan warna pada halaman profil. Atau mungkin sesuatu yang lebih terlokalisasi. Misalnya, Anda dapat memilih warna catatan di aplikasi Google Keep.
Tema biasanya melibatkan kompilasi stylesheet terpisah untuk menimpa nilai default dengan preferensi pengguna, atau kompilasi stylesheet yang berbeda untuk setiap pengguna. Kedua hal ini bisa sulit dan berdampak pada kinerja.
Dengan properti kustom, kita tidak perlu mengkompilasi stylesheet yang berbeda; kita hanya perlu memperbarui nilai properti sesuai dengan preferensi pengguna. Karena mereka adalah nilai yang diwarisi, jika kita melakukan ini pada elemen root, mereka dapat digunakan di mana saja dalam aplikasi kita.
Memanfaatkan Properti Dinamis Global
Properti kustom peka terhadap huruf besar/kecil dan karena sebagian besar properti kustom akan bersifat lokal, jika Anda menggunakan properti dinamis global, masuk akal untuk menggunakan huruf kapital.
:root { --THEME-COLOR: var(--user-theme-color, #d33a2c); }
Kapitalisasi variabel sering menandakan konstanta global. Bagi kami, ini akan menandakan bahwa properti diatur di tempat lain dalam aplikasi dan bahwa kami mungkin tidak boleh mengubahnya secara lokal.
Hindari Mengatur Properti Dinamis Global Secara Langsung
Properti kustom menerima nilai fallback. Ini dapat berguna untuk menghindari penimpaan nilai properti kustom global secara langsung dan memisahkan nilai pengguna. Kita dapat menggunakan nilai fallback untuk melakukan ini.
Contoh di atas menetapkan nilai --THEME-COLOR
ke nilai --user-theme-color
jika ada. Jika --user-theme-color
tidak disetel, nilai #d33a2c
akan digunakan. Dengan cara ini, kita tidak perlu memberikan fallback setiap kali kita menggunakan --THEME-COLOR
.
Anda mungkin berharap pada contoh di bawah ini bahwa latar belakang akan disetel ke green
. Namun, nilai --user-theme-color
belum disetel pada elemen root, sehingga nilai --THEME-COLOR
tidak berubah.
:root { --THEME-COLOR: var(--user-theme-color, #d33a2c); } body { --user-theme-color: green; background: var(--THEME-COLOR); }
Menyetel properti dinamis global secara tidak langsung seperti ini melindunginya agar tidak ditimpa secara lokal dan memastikan setelan pengguna selalu diwarisi dari elemen root. Ini adalah konvensi yang berguna untuk menjaga nilai tema Anda dan menghindari pewarisan yang tidak diinginkan.
Jika kita ingin mengekspos properti tertentu ke pewarisan, kita dapat mengganti :root
selector dengan *
selector:
* { --THEME-COLOR: var(--user-theme-color, #d33a2c); } body { --user-theme-color: green; background: var(--THEME-COLOR); }
Sekarang nilai --THEME-COLOR
dihitung ulang untuk setiap elemen dan oleh karena itu nilai lokal --user-theme-color
dapat digunakan. Dengan kata lain, warna latar belakang dalam contoh ini akan menjadi green
.
Anda dapat melihat beberapa contoh lebih detail dari pola ini di bagian Memanipulasi Warna Dengan Properti Kustom.
Memperbarui Properti Khusus Dengan JavaScript
Jika Anda ingin mengatur properti khusus menggunakan JavaScript, ada API yang cukup sederhana dan terlihat seperti ini:
const elm = document.documentElement; elm.style.setProperty('--USER-THEME-COLOR', 'tomato');
Di sini saya menyetel nilai --USER-THEME-COLOR
pada elemen dokumen, atau dengan kata lain, elemen :root
yang akan diwarisi oleh semua elemen.
Ini bukan API baru; itu adalah metode JavaScript yang sama untuk memperbarui gaya pada suatu elemen. Ini adalah gaya sebaris sehingga mereka akan memiliki kekhususan yang lebih tinggi daripada CSS biasa.
Ini berarti mudah untuk menerapkan penyesuaian lokal:
.note { --note-color: #eaeaea; } .note { background: var(--note-color); }
Di sini saya menetapkan nilai default untuk --note-color
dan memasukkan ini ke komponen .note
. Saya memisahkan deklarasi variabel dari deklarasi properti, bahkan dalam contoh sederhana ini.
const elm = document.querySelector('#note-uid'); elm.style.setProperty('--note-color', 'yellow');
Saya kemudian menargetkan instance spesifik dari elemen .note
dan mengubah nilai properti kustom --note-color
untuk elemen itu saja. Ini sekarang akan memiliki spesifisitas yang lebih tinggi daripada nilai default.
Anda dapat melihat bagaimana ini bekerja dengan contoh ini menggunakan React. Preferensi pengguna ini dapat disimpan di penyimpanan lokal atau, mungkin dalam kasus aplikasi yang lebih besar, dalam database.
Memanipulasi Warna Dengan Properti Kustom
Selain nilai hex dan warna bernama, CSS memiliki fungsi warna seperti rgb()
dan hsl()
. Ini memungkinkan kita untuk menentukan komponen individual dari warna seperti rona atau kecerahan. Properti kustom dapat digunakan bersama dengan fungsi warna.
:root { --hue: 25; } body { background: hsl(var(--hue), 80%, 50%); }
Ini berguna, tetapi beberapa fitur praprosesor yang paling banyak digunakan adalah fungsi warna tingkat lanjut yang memungkinkan kita untuk memanipulasi warna menggunakan fungsi seperti mencerahkan, menggelapkan, atau desaturasi:
darken($base-color, 10%); lighten($base-color, 10%); desaturate($base-color, 20%);
Akan berguna untuk memiliki beberapa fitur ini di browser. Mereka akan datang, tetapi sampai kita memiliki fungsi modifikasi warna asli di CSS, properti khusus dapat mengisi beberapa celah itu.
Kita telah melihat bahwa properti khusus dapat digunakan di dalam fungsi warna yang ada seperti rgb()
dan hsl()
tetapi mereka juga dapat digunakan di calc()
. Artinya, kita dapat mengubah bilangan real menjadi persentase dengan mengalikannya, misalnya calc(50 * 1%)
= 50%
.
:root { --lightness: 50; } body { background: hsl(25, 80%, calc(var(--lightness) * 1%)); }
Alasan kami ingin menyimpan nilai lightness sebagai bilangan real adalah agar kami dapat memanipulasinya dengan calc
sebelum mengubahnya menjadi persentase. Misalnya, jika saya ingin menggelapkan warna sebesar 20%
, saya dapat mengalikan kecerahannya dengan 0.8
. Kita dapat membuat ini sedikit lebih mudah dibaca dengan memisahkan perhitungan lightness menjadi properti kustom yang dicakup secara lokal:
:root { --lightness: 50; } body { --lightness: calc(var(--lightness * 0.8)); background: hsl(25, 80%, calc(var(--lightness) * 1%)); }
Kami bahkan dapat mengabstraksi lebih banyak perhitungan dan membuat sesuatu seperti fungsi modifikasi warna di CSS menggunakan properti khusus. Contoh ini mungkin terlalu rumit untuk sebagian besar kasus tema yang praktis, tetapi contoh ini menunjukkan kekuatan penuh dari properti kustom dinamis.
Sederhanakan Tema
Salah satu keuntungan menggunakan properti kustom adalah kemampuan untuk menyederhanakan tema. Aplikasi tidak perlu mengetahui bagaimana properti kustom digunakan. Sebagai gantinya, kami menggunakan JavaScript atau kode sisi server untuk menetapkan nilai properti khusus. Bagaimana nilai-nilai ini digunakan ditentukan oleh stylesheet.
Ini berarti sekali lagi kita dapat memisahkan logika dari desain. Jika Anda memiliki tim desain teknis, penulis dapat memperbarui lembar gaya dan memutuskan cara menerapkan properti khusus tanpa mengubah satu baris JavaScript atau kode backend.
Properti khusus juga memungkinkan untuk memindahkan beberapa kerumitan tema ke dalam CSS dan kerumitan ini dapat berdampak negatif pada pemeliharaan CSS Anda, jadi ingatlah untuk membuatnya tetap sederhana sedapat mungkin.
Menggunakan Properti Kustom Sekarang
Bahkan jika Anda mendukung IE10 dan 11, Anda dapat mulai menggunakan properti khusus hari ini. Sebagian besar contoh dalam artikel ini berkaitan dengan cara kita menulis dan menyusun CSS. Manfaatnya signifikan dalam hal pemeliharaan, namun, sebagian besar contoh hanya mengurangi apa yang dapat dilakukan dengan kode yang lebih kompleks.
Saya menggunakan alat yang disebut variabel postcss-css untuk mengubah sebagian besar fitur properti khusus menjadi representasi statis dari kode yang sama. Alat serupa lainnya mengabaikan properti khusus di dalam kueri media atau pemilih kompleks, memperlakukan properti khusus seperti variabel praprosesor.
Apa yang tidak dapat dilakukan alat ini adalah meniru fitur runtime dari properti kustom. Ini berarti tidak ada fitur dinamis seperti tema atau mengubah properti dengan JavaScript. Ini mungkin baik-baik saja dalam banyak situasi. Bergantung pada situasinya, penyesuaian UI dapat dianggap sebagai peningkatan progresif dan tema default dapat diterima dengan sempurna untuk browser lama.
Memuat Lembar Gaya yang Benar
Ada banyak cara Anda dapat menggunakan postCSS. Saya menggunakan proses gulp
untuk mengkompilasi stylesheet terpisah untuk browser yang lebih baru dan lebih lama. Versi sederhana dari tugas gulp
saya terlihat seperti ini:
import gulp from "gulp"; import sass from "gulp-sass"; import postcss from "gulp-postcss"; import rename from "gulp-rename"; import cssvariables from "postcss-css-variables"; import autoprefixer from "autoprefixer"; import cssnano from "cssnano"; gulp.task("css-no-vars", () => gulp .src("./src/css/*.scss") .pipe(sass().on("error", sass.logError)) .pipe(postcss([cssvariables(), cssnano()])) .pipe(rename({ extname: ".no-vars.css" })) .pipe(gulp.dest("./dist/css")) ); gulp.task("css", () => gulp .src("./src/css/*.scss") .pipe(sass().on("error", sass.logError)) .pipe(postcss([cssnano()])) .pipe(rename({ extname: ".css" })) .pipe(gulp.dest("./dist/css")) );
Ini menghasilkan dua file CSS: yang biasa dengan properti khusus ( styles.css
) dan satu untuk browser lama ( styles.no-vars.css
). Saya ingin IE10 dan 11 dilayani styles.no-vars.css
dan browser lain untuk mendapatkan file CSS biasa.
Biasanya, saya menganjurkan menggunakan kueri fitur tetapi IE11 tidak mendukung kueri fitur dan kami telah menggunakan properti khusus secara ekstensif sehingga menyajikan lembar gaya yang berbeda masuk akal dalam kasus ini.
Secara cerdas menyajikan stylesheet yang berbeda dan menghindari kilasan konten tanpa gaya bukanlah tugas yang mudah. Jika Anda tidak memerlukan fitur dinamis dari properti kustom, Anda dapat mempertimbangkan untuk menyajikan semua browser styles.no-vars.css
dan menggunakan properti kustom hanya sebagai alat pengembangan.
Jika Anda ingin memanfaatkan sepenuhnya semua fitur dinamis dari properti kustom, saya sarankan menggunakan teknik CSS yang penting. Mengikuti teknik ini, lembar gaya utama dimuat secara asinkron sementara CSS penting dirender sebaris. Header halaman Anda mungkin terlihat seperti ini:
<head> <style> /* inlined critical CSS */ </style> <script> loadCSS('non-critical.css'); </script> </head>
Kita dapat memperluas ini untuk memuat baik styles.css
atau styles.no-vars.css
tergantung pada apakah browser mendukung properti kustom. Kami dapat mendeteksi dukungan seperti ini:
if ( window.CSS && CSS.supports('color', 'var(--test)') ) { loadCSS('styles.css'); } else { loadCSS('styles.no-vars.css'); }
Kesimpulan
Jika Anda telah berjuang untuk mengatur CSS secara efisien, mengalami kesulitan dengan komponen responsif, ingin menerapkan tema sisi klien, atau hanya ingin memulai dengan langkah yang benar dengan properti kustom, panduan ini akan memberi tahu Anda semua yang perlu Anda ketahui.
Itu datang untuk memahami perbedaan antara variabel dinamis dan statis dalam CSS serta beberapa aturan sederhana:
- Pisahkan logika dari desain;
- Jika properti CSS berubah, pertimbangkan untuk menggunakan properti kustom;
- Ubah nilai properti kustom, bukan properti kustom mana yang digunakan;
- Variabel global biasanya statis.
If you follow these conventions, you will find that working with custom properties is a whole lot easier than you think. This might even change how you approach CSS in general.
Bacaan lebih lanjut
- “It's Time To Start Using Custom Properties,” Serg Hospodarets
A general introduction to the syntax and the features of custom properties. - “Pragmatic, Practical, And Progressive Theming With Custom Properties,” Harry Roberts
More useful information on theming. - Custom Properties Collection, Mike Riethmuller on CodePen
A number of different examples you can experiment with.