Menata Komponen Web Menggunakan Lembar Gaya Bersama

Diterbitkan: 2022-03-10
Ringkasan cepat Komponen web adalah fitur baru yang luar biasa dari web, memungkinkan pengembang untuk menentukan elemen HTML kustom mereka sendiri. Saat digabungkan dengan panduan gaya, komponen web dapat membuat API komponen, yang memungkinkan pengembang berhenti menyalin dan menempelkan cuplikan kode dan sebagai gantinya hanya menggunakan elemen DOM. Dengan menggunakan shadow DOM, kita dapat merangkum komponen web dan tidak perlu khawatir tentang perang spesifisitas dengan style sheet lain di halaman. Namun, komponen web dan panduan gaya saat ini tampaknya bertentangan satu sama lain.

Komponen web adalah fitur baru yang luar biasa dari web, memungkinkan pengembang untuk menentukan elemen HTML khusus mereka sendiri. Saat digabungkan dengan panduan gaya, komponen web dapat membuat API komponen, yang memungkinkan pengembang berhenti menyalin dan menempelkan cuplikan kode dan sebagai gantinya hanya menggunakan elemen DOM. Dengan menggunakan shadow DOM, kita dapat merangkum komponen web dan tidak perlu khawatir tentang perang spesifisitas dengan style sheet lain di halaman.

Namun, komponen web dan panduan gaya saat ini tampaknya bertentangan satu sama lain. Di satu sisi, panduan gaya menyediakan seperangkat aturan dan gaya yang diterapkan secara global ke halaman dan memastikan konsistensi di seluruh situs web. Di sisi lain, komponen web dengan shadow DOM mencegah gaya global apa pun menembus enkapsulasinya, sehingga mencegah panduan gaya memengaruhinya.

Bacaan Lebih Lanjut tentang SmashingMag:

  • Menegakkan Praktik Terbaik Dalam Sistem Berbasis Komponen
  • Cara Menggunakan Preprocessor CSS KURANG Untuk Style Sheets yang Lebih Cerdas
  • Menyelam Jauh Ke Dalam Adobe Edge Reflow

Jadi, bagaimana keduanya dapat hidup berdampingan, dengan panduan gaya global yang terus memberikan konsistensi dan gaya, bahkan untuk komponen web dengan shadow DOM? Untungnya, ada solusi yang berfungsi saat ini, dan lebih banyak solusi yang akan datang, yang memungkinkan panduan gaya global menyediakan gaya untuk komponen web. (Untuk sisa artikel ini, saya akan menggunakan istilah "komponen web" untuk merujuk ke elemen khusus dengan shadow DOM.)

Lebih banyak setelah melompat! Lanjutkan membaca di bawah ini

Apa Seharusnya Gaya Panduan Gaya Global Dalam Komponen Web?

Sebelum membahas cara mendapatkan panduan gaya global untuk menata gaya komponen web, kita harus mendiskusikan apa yang harus dan tidak boleh dicoba untuk gaya.

Pertama-tama, praktik terbaik saat ini untuk komponen web menyatakan bahwa komponen web, termasuk gayanya, harus dienkapsulasi, sehingga tidak bergantung pada sumber daya eksternal apa pun untuk berfungsi. Ini memungkinkannya untuk digunakan di mana saja di dalam atau di luar situs web, bahkan ketika panduan gaya tidak tersedia.

Di bawah ini adalah komponen web formulir masuk sederhana yang merangkum semua gayanya.

 <template> <style> :host { color: #333333; font: 16px Arial, sans-serif; } p { margin: 0; } p + p { margin-top: 20px; } a { color: #1f66e5; } label { display: block; margin-bottom: 5px; } input[type="text"], input[type="password"] { background-color: #eaeaea; border: 1px solid grey; border-radius: 4px; box-sizing: border-box; color: inherit; font: inherit; padding: 10px 10px; width: 100%; } input[type="submit"] { font: 16px/1.6 Arial, sans-serif; color: white; background: cornflowerblue; border: 1px solid #1f66e5; border-radius: 4px; padding: 10px 10px; width: 100%; } .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <div class="container"> <form action="#"> <p> <label for="username">User Name</label> <input type="text" name="username"> </p> <p> <label for="password">Password</label> <input type="password" name="password"> </p> <p> <input type="submit" value="Login"> </p> <p class="footnote">Not registered? <a href="#">Create an account</a></p> </form> </div> </template> <script> const doc = (document._currentScript || document.currentScript).ownerDocument; const template = doc.querySelector('#login-form-template'); customElements.define('login-form', class extends HTMLElement { constructor() { super(); const root = this.attachShadow({mode: 'closed'}); const temp = document.importNode(template.content, true); root.appendChild(temp); } }); </script>

Catatan: Contoh kode ditulis dalam spesifikasi versi 1 untuk komponen web.

Formulir masuk dengan nama pengguna dan kata sandi.
Komponen web formulir masuk sederhana

Namun, mengenkapsulasi sepenuhnya setiap komponen web pasti akan menyebabkan banyak CSS duplikat, terutama saat mengatur tipografi dan gaya elemen asli. Jika pengembang ingin menggunakan paragraf, tag jangkar, atau bidang input di komponen web mereka, itu harus ditata seperti bagian situs web lainnya.

Jika kita sepenuhnya merangkum semua gaya yang dibutuhkan komponen web, maka CSS untuk paragraf penataan gaya, tag jangkar, bidang input, dan sebagainya akan diduplikasi di semua komponen web yang menggunakannya. Ini tidak hanya akan meningkatkan biaya pemeliharaan, tetapi juga menyebabkan ukuran unduhan yang jauh lebih besar bagi pengguna.

Alih-alih merangkum semua gaya, komponen web seharusnya hanya merangkum gaya uniknya dan kemudian bergantung pada sekumpulan gaya bersama untuk menangani gaya untuk yang lainnya. Gaya bersama ini pada dasarnya akan menjadi semacam Normalize.css, yang dapat digunakan komponen web untuk memastikan bahwa elemen asli ditata sesuai dengan panduan gaya.

Pada contoh sebelumnya, komponen web formulir masuk akan mendeklarasikan gaya hanya untuk dua kelas uniknya: .container dan .footnote . Gaya lainnya akan termasuk dalam lembar gaya bersama dan akan menata gaya paragraf, tag jangkar, bidang input, dan sebagainya.

Singkatnya, panduan gaya tidak boleh mencoba memberi gaya pada komponen web, melainkan harus menyediakan serangkaian gaya bersama yang dapat digunakan komponen web untuk mencapai tampilan yang konsisten.

Bagaimana Menata Shadow DOM Dengan Lembar Gaya Eksternal Dulu Dilakukan

Spesifikasi awal untuk komponen web (dikenal sebagai versi 0) memungkinkan setiap style sheet eksternal untuk menembus shadow DOM melalui penggunaan ::shadow atau /deep/ pemilih CSS. Penggunaan ::shadow dan /deep/ memungkinkan Anda untuk memiliki panduan gaya menembus shadow DOM dan mengatur gaya bersama, baik komponen web menginginkannya atau tidak.

 /* Style all p tags inside a web components shadow DOM */ login-form::shadow p { color: red; }

Dengan munculnya versi terbaru dari spesifikasi komponen web (dikenal sebagai versi 1), penulis telah menghapus kemampuan lembar gaya eksternal untuk menembus shadow DOM, dan mereka tidak memberikan alternatif. Alih-alih, filosofi telah berubah dari menggunakan naga untuk mendesain komponen web menjadi menggunakan jembatan. Dengan kata lain, pembuat komponen web harus bertanggung jawab atas aturan gaya eksternal apa yang diizinkan untuk menata gaya komponen mereka, daripada dipaksa untuk mengizinkannya.

Sayangnya, filosofi itu belum benar-benar sesuai dengan web, yang membuat kita bingung. Untungnya, beberapa solusi yang tersedia saat ini, dan beberapa yang akan datang dalam waktu yang tidak terlalu lama, akan memungkinkan style sheet bersama untuk menata komponen web.

Apa yang Dapat Anda Lakukan Hari Ini

Ada tiga teknik yang dapat Anda gunakan hari ini yang memungkinkan komponen web berbagi gaya: @import , elemen khusus, dan pustaka komponen web.

Menggunakan @import

Satu-satunya cara asli hari ini untuk membawa style sheet ke dalam komponen web adalah dengan menggunakan @import . Meskipun ini berhasil, ini adalah anti-pola. Untuk komponen web, bagaimanapun, ini adalah masalah kinerja yang lebih besar.

 <template> <style> @import "styleguide.css" </style> <style> .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <!-- rest of template DOM --> </template>

Biasanya, @import adalah anti-pola karena mengunduh semua lembar gaya secara seri, bukan paralel, terutama jika mereka bersarang. Dalam situasi kami, mengunduh satu lembar gaya secara seri tidak dapat membantu, jadi secara teori itu akan baik-baik saja. Tetapi ketika saya menguji ini di Chrome, hasilnya menunjukkan bahwa menggunakan @import menyebabkan halaman dirender hingga setengah detik lebih lambat daripada saat hanya menyematkan gaya langsung ke komponen web.

Catatan: Karena perbedaan cara kerja polyfill dari impor HTML dibandingkan dengan impor HTML asli, WebPagetest.org hanya dapat digunakan untuk memberikan hasil yang andal di browser yang secara asli mendukung impor HTML (yaitu Chrome).

Grafik batang kinerja komponen web asli.
Hasil dari tiga pengujian kinerja menunjukkan bahwa @import menyebabkan browser merender hingga setengah detik lebih lambat daripada saat hanya menyematkan gaya langsung ke komponen web.

Pada akhirnya, @import masih menjadi anti-pola dan dapat menjadi masalah kinerja di komponen web. Jadi, itu bukan solusi yang bagus.

Jangan Gunakan Shadow DOM

Karena masalah dengan mencoba memberikan gaya bersama ke komponen web berasal dari penggunaan shadow DOM, salah satu cara untuk menghindari masalah sepenuhnya adalah dengan tidak menggunakan shadow DOM.

Dengan tidak menggunakan shadow DOM, Anda akan membuat elemen kustom alih-alih komponen web (lihat samping di bawah), satu-satunya perbedaan adalah tidak adanya shadow DOM dan pelingkupan. Elemen Anda akan tunduk pada gaya halaman, tetapi kita sudah harus menghadapinya hari ini, jadi tidak ada yang belum kita ketahui cara menanganinya. Elemen kustom didukung penuh oleh polyfill webcomponentjs, yang memiliki dukungan browser yang hebat.

Manfaat terbesar dari elemen kustom adalah Anda dapat membuat pustaka pola menggunakannya hari ini, dan Anda tidak perlu menunggu hingga masalah gaya bersama terpecahkan. Dan karena satu-satunya perbedaan antara komponen web dan elemen kustom adalah shadow DOM, Anda selalu dapat mengaktifkan shadow DOM di elemen kustom Anda setelah solusi untuk gaya bersama tersedia.

Jika Anda memutuskan untuk membuat elemen kustom, perhatikan beberapa perbedaan antara elemen kustom dan komponen web.

Pertama, karena gaya untuk elemen kustom tunduk pada gaya halaman dan sebaliknya, Anda harus memastikan bahwa pemilih Anda tidak menyebabkan konflik apa pun. Jika halaman Anda sudah menggunakan panduan gaya, biarkan gaya untuk elemen khusus di panduan gaya, dan buat elemen menampilkan DOM dan struktur kelas yang diharapkan.

Dengan membiarkan gaya dalam panduan gaya, Anda akan membuat jalur migrasi yang mulus untuk pengembang Anda, karena mereka dapat terus menggunakan panduan gaya seperti sebelumnya, tetapi kemudian perlahan-lahan bermigrasi menggunakan elemen kustom baru jika mereka mampu. Setelah semua orang menggunakan elemen kustom, Anda dapat memindahkan gaya untuk berada di dalam elemen untuk menyatukannya dan memungkinkan pemfaktoran ulang komponen web dengan lebih mudah nanti.

Kedua, pastikan untuk mengenkapsulasi kode JavaScript apa pun di dalam ekspresi fungsi yang segera dipanggil (IFFE), sehingga Anda tidak menghapus variabel apa pun ke lingkup global. Selain tidak menyediakan pelingkupan CSS, elemen khusus tidak menyediakan pelingkupan JavaScript.

Ketiga, Anda harus menggunakan fungsi connectedCallback dari elemen kustom untuk menambahkan DOM template ke elemen. Menurut spesifikasi komponen web, elemen khusus tidak boleh menambahkan anak selama fungsi konstruktor, jadi Anda harus menunda penambahan DOM ke fungsi connectedCallback .

Terakhir, elemen <slot> tidak berfungsi di luar shadow DOM. Ini berarti Anda harus menggunakan metode yang berbeda untuk menyediakan cara bagi pengembang untuk memasukkan konten mereka ke dalam elemen kustom Anda. Biasanya, ini hanya memerlukan manipulasi DOM sendiri untuk memasukkan konten mereka di tempat yang Anda inginkan.

Namun, karena tidak ada pemisahan antara DOM bayangan dan DOM ringan dengan elemen khusus, Anda juga harus sangat berhati-hati untuk tidak menata DOM yang disisipkan, karena gaya berjenjang elemen Anda.

 <!-- login-form.html --> <template> <style> login-form .container { max-width: 300px; padding: 50px; border: 1px solid grey; } login-form .footnote { text-align: center; } </style> <!-- Rest of template DOM --> </template> <script> (function() { const doc = (document._currentScript || document.currentScript).ownerDocument; const template = doc.querySelector('#login-form-template'); customElements.define('login-form', class extends HTMLElement { constructor() { super(); } // Without the shadow DOM, we have to manipulate the custom element // after it has been inserted in the DOM. connectedCallback() { const temp = document.importNode(template.content, true); this.appendChild(temp); } }); })(); </script>
 <!-- index.html --> <link rel="stylesheet" href="styleguide.css"> <link rel="import" href="login-form.html"> <login-form></login-form>

Dalam hal kinerja, elemen kustom hampir secepat komponen web tidak digunakan (yaitu menautkan lembar gaya bersama di head dan hanya menggunakan elemen DOM asli). Dari semua teknik yang dapat Anda gunakan hari ini, ini adalah yang tercepat.

Grafik batang kinerja elemen khusus.
Hasil dari dua tes kinerja menunjukkan bahwa elemen kustom hampir secepat tidak menggunakan komponen web sama sekali.

Selain: Elemen kustom masih merupakan komponen web untuk semua maksud dan tujuan. Istilah "komponen web" digunakan untuk menggambarkan empat teknologi terpisah: elemen khusus, tag template, impor HTML, dan shadow DOM.

Sayangnya, istilah tersebut telah digunakan untuk menggambarkan segala sesuatu yang menggunakan kombinasi dari empat teknologi. Hal ini menyebabkan banyak kebingungan tentang apa yang orang maksudkan ketika mereka mengatakan "komponen web". Seperti yang ditemukan Rob Dodson, saya merasa terbantu menggunakan istilah yang berbeda ketika berbicara tentang elemen khusus dengan dan tanpa shadow DOM.

Sebagian besar pengembang yang saya ajak bicara cenderung mengaitkan istilah "komponen web" dengan elemen khusus yang menggunakan shadow DOM. Jadi, untuk tujuan artikel ini, saya telah membuat perbedaan buatan antara komponen web dan elemen kustom.

Menggunakan Pustaka Komponen Web

Solusi lain yang dapat Anda gunakan saat ini adalah pustaka komponen web, seperti Polymer, SkateJS atau X-Tag. Pustaka ini membantu mengisi lubang dukungan saat ini dan juga dapat menyederhanakan kode yang diperlukan untuk membuat komponen web. Mereka juga biasanya menyediakan fitur tambahan yang membuat menulis komponen web lebih mudah.

Misalnya, Polymer memungkinkan Anda membuat komponen web sederhana hanya dalam beberapa baris JavaScript. Manfaat tambahannya adalah bahwa Polymer menyediakan solusi untuk menggunakan shadow DOM dan lembar gaya bersama. Ini berarti Anda dapat membuat komponen web hari ini yang berbagi gaya.

Untuk melakukan ini, buat apa yang mereka sebut modul gaya, yang berisi semua gaya bersama. Ini bisa berupa tag <style> dengan gaya bersama sebaris atau <link rel=“import”> yang menunjuk ke lembar gaya bersama. Dalam kedua kasus tersebut, sertakan gaya dalam komponen web Anda dengan <style include> , lalu Polymer akan mengurai gaya dan menambahkannya sebagai tag <style> sebaris ke komponen web Anda.

 <!-- shared-styles.html --> <dom-module> <!-- Link to a shared style sheet --> <!-- <link rel="import" href="styleguide.css"> --> <!-- Inline the shared styles --> <template> <style> :host { color: #333333; font: 16px Arial, sans-serif; } /* Rest of shared CSS */ </style> </template> </dom-module>
 <!-- login-form.html --> <link rel="import" href="../polymer/polymer.html"> <link rel="import" href="../shared-styles/shared-styles.html"> <dom-module> <template> <!-- Include the shared styles --> <style include="shared-styles"></style> <style> .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <!-- Rest of template DOM --> </template> <script> Polymer({ is: 'login-form' }); </script> </dom-module>

Satu-satunya downside menggunakan perpustakaan adalah dapat menunda waktu rendering komponen web Anda. Ini seharusnya tidak mengejutkan karena mengunduh kode perpustakaan dan memprosesnya membutuhkan waktu. Komponen web apa pun di halaman tidak dapat mulai dirender hingga pustaka selesai diproses.

Dalam kasus Polymer, ini dapat menunda waktu rendering halaman hingga setengah detik dibandingkan dengan komponen web asli. Modul gaya yang menyematkan gaya sedikit lebih lambat daripada modul gaya yang menautkan gaya, dan menyematkan gaya langsung ke komponen web sama cepatnya dengan menggunakan modul gaya.

Sekali lagi, Polymer tidak melakukan apa pun secara khusus untuk membuat waktu rendering lebih lambat. Mengunduh perpustakaan Polimer dan memproses semua fitur luar biasa, ditambah membuat semua ikatan template, membutuhkan waktu. Ini hanya pertukaran yang harus Anda lakukan untuk menggunakan pustaka komponen web.

Grafik batang kinerja komponen web Polimer.

Hasil dari pengujian kinerja menunjukkan bahwa, dengan menggunakan Polimer, komponen web akan merender hingga setengah detik lebih lambat daripada komponen web asli.

Janji Masa Depan

Jika tidak ada solusi saat ini yang berhasil untuk Anda, jangan putus asa. Jika semuanya berjalan dengan baik, dalam beberapa bulan hingga beberapa tahun, kami akan dapat menggunakan gaya bersama menggunakan beberapa pendekatan berbeda.

Properti Khusus

Properti khusus (atau variabel CSS, demikian sebutannya) adalah cara untuk menyetel dan menggunakan variabel dalam CSS. Gagasan ini bukanlah hal baru bagi praprosesor CSS, tetapi sebagai fitur CSS asli, properti khusus sebenarnya lebih kuat daripada variabel praprosesor.

Untuk mendeklarasikan properti kustom, gunakan notasi properti kustom dari –my-variable: value , dan akses variabel menggunakan property: var(–my-variable) . Properti kustom mengalir seperti aturan CSS lainnya, sehingga nilainya diturunkan dari induknya dan dapat diganti. Satu-satunya peringatan untuk properti khusus adalah bahwa mereka harus dideklarasikan di dalam pemilih dan tidak dapat dideklarasikan sendiri, tidak seperti variabel praprosesor.

 <style> /* Declare the custom property */ html { --main-bg-color: red; } /* Use the custom property */ input { background: var(--main-bg-color); } </style>

Satu hal yang membuat properti kustom begitu kuat adalah kemampuannya untuk menembus shadow DOM. Ini bukan ide yang sama dengan /deep/ dan ::shadow selector karena mereka tidak memaksa masuk ke komponen web. Sebagai gantinya, pembuat komponen web harus menggunakan properti kustom di CSS mereka agar dapat diterapkan. Ini berarti bahwa pembuat komponen web dapat membuat API properti khusus yang dapat digunakan konsumen komponen web untuk menerapkan gaya mereka sendiri.

 <template> <style> /* Declare the custom property API */ :host { --main-bg-color: brown; } .one { color: var(--main-bg-color); } </style> <div class="one">Hello World</div> </template> <script> /* Code to set up my-element web component */ </script> <my-element></my-element> <style> /* Override the custom variable with own value */ my-element { --main-bg-color: red; } </style>

Dukungan browser untuk properti khusus sangat bagus. Satu-satunya alasan itu bukan solusi yang dapat Anda gunakan hari ini adalah karena tidak ada polyfill yang berfungsi tanpa Elemen Kustom versi 1. Tim di belakang polyfill webcomponentjs saat ini sedang bekerja untuk menambahkannya, tetapi belum dirilis dan dalam keadaan dibangun, artinya jika Anda hash aset Anda untuk produksi, Anda tidak dapat menggunakannya. Dari apa yang saya pahami, itu akan dirilis sekitar awal tahun depan.

Meski begitu, properti kustom bukanlah metode yang baik untuk berbagi gaya antar komponen web. Karena mereka hanya dapat digunakan untuk mendeklarasikan satu nilai properti, komponen web masih perlu menyematkan semua gaya panduan gaya, meskipun nilainya diganti dengan variabel.

Properti kustom lebih cocok untuk opsi tema, daripada gaya bersama. Karena itu, properti khusus bukanlah solusi yang tepat untuk masalah kita.

/* Gunakan properti kustom */ input { background: var(–main-bg-color); } </gaya>

Satu hal yang membuat properti kustom begitu kuat adalah kemampuannya untuk menembus shadow DOM. Ini bukan ide yang sama dengan /deep/ dan ::shadow selector karena mereka tidak memaksa masuk ke komponen web. Sebagai gantinya, pembuat komponen web harus menggunakan properti kustom di CSS mereka agar dapat diterapkan. Ini berarti bahwa pembuat komponen web dapat membuat API properti khusus yang dapat digunakan konsumen komponen web untuk menerapkan gaya mereka sendiri.

 <template> <style> /* Declare the custom property API */ :host { --main-bg-color: brown; } .one { color: var(--main-bg-color); } </style> <div class="one">Hello World</div> </template> <script> /* Code to set up my-element web component */ </script> <my-element></my-element> <style> /* Override the custom variable with own value */ my-element { --main-bg-color: red; } </style>

Dukungan browser untuk properti khusus sangat bagus. Satu-satunya alasan itu bukan solusi yang dapat Anda gunakan hari ini adalah karena tidak ada polyfill yang berfungsi tanpa Elemen Kustom versi 1. Tim di belakang polyfill webcomponentjs saat ini sedang bekerja untuk menambahkannya, tetapi belum dirilis dan dalam keadaan dibangun, artinya jika Anda hash aset Anda untuk produksi, Anda tidak dapat menggunakannya. Dari apa yang saya pahami, itu akan dirilis sekitar awal tahun depan.

Meski begitu, properti kustom bukanlah metode yang baik untuk berbagi gaya antar komponen web. Karena mereka hanya dapat digunakan untuk mendeklarasikan satu nilai properti, komponen web masih perlu menyematkan semua gaya panduan gaya, meskipun nilainya diganti dengan variabel.

Properti kustom lebih cocok untuk opsi tema, daripada gaya bersama. Karena itu, properti khusus bukanlah solusi yang tepat untuk masalah kita.

@terapkan Aturan

Selain properti khusus, CSS juga mendapatkan aturan @apply . Terapkan aturan pada dasarnya adalah campuran untuk dunia CSS. Mereka dideklarasikan dengan cara yang mirip dengan properti kustom tetapi dapat digunakan untuk mendeklarasikan grup properti, bukan hanya nilai properti. Sama seperti properti khusus, nilainya dapat diwarisi dan diganti, dan harus dideklarasikan di dalam pemilih agar berfungsi.

 <style> /* Declare rule */ html { --typography: { font: 16px Arial, sans-serif; color: #333333; } } /* Use rule */ input { @apply --typography; } </style>

Dukungan browser untuk aturan @apply pada dasarnya tidak ada. Chrome saat ini mendukungnya di balik bendera fitur (yang tidak dapat saya temukan), tetapi hanya itu. Juga tidak ada polyfill yang berfungsi untuk alasan yang sama karena tidak ada polyfill untuk properti khusus. Tim polyfill webcomponentjs juga bekerja untuk menambahkan aturan @apply , bersama dengan properti khusus, sehingga keduanya akan tersedia setelah versi baru dirilis.

Tidak seperti properti khusus, aturan @apply adalah solusi yang jauh lebih baik untuk berbagi gaya. Karena mereka dapat menyiapkan sekelompok deklarasi properti, Anda dapat menggunakannya untuk menyiapkan gaya default untuk semua elemen asli dan kemudian menggunakannya di dalam komponen web. Untuk melakukan ini, Anda harus membuat aturan @apply untuk setiap elemen asli.

Namun, untuk menggunakan gaya, Anda harus menerapkannya secara manual ke setiap elemen asli, yang masih akan menduplikasi deklarasi gaya di setiap komponen web. Meskipun itu lebih baik daripada menyematkan semua gaya, itu juga tidak terlalu nyaman karena menjadi boilerplate di bagian atas setiap komponen web, yang harus Anda ingat untuk ditambahkan agar gaya berfungsi dengan baik.

 /* styleguide.css */ html { --typography: { color: #333333; font: 16px Arial, sans-serif; } --paragraph: { margin: 0; } --label { display: block; margin-bottom: 5px; } --input-text { background-color: #eaeaea; border: 1px solid grey; border-radius: 4px; box-sizing: border-box; color: inherit; font: inherit; padding: 10px 10px; width: 100%; } --input-submit { font: 16px/1.6 Arial, sans-serif; color: white; background: cornflowerblue; border: 1px solid #1f66e5; border-radius: 4px; padding: 10px 10px; width: 100%; } /* And so on for every native element */ }
 <!-- login-form.html --> <template> <style> :host { @apply --typography; } p { @apply --paragraph; } label { @apply --label; } input-text { @apply --input-text; } .input-submit { @apply --input-submit; } .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <!-- Rest of template DOM --> </template>

Karena kebutuhan untuk boilerplate yang luas, saya tidak percaya bahwa aturan @apply akan menjadi solusi yang baik untuk berbagi gaya antar komponen web. Mereka adalah solusi yang bagus untuk bertema.

di Shadow DOM

Menurut spesifikasi komponen web, browser mengabaikan <link rel=“stylesheet”> di shadow DOM, memperlakukannya seperti yang mereka lakukan di dalam fragmen dokumen. Ini mencegah kami untuk dapat menautkan dalam gaya bersama apa pun di komponen web kami, yang sangat disayangkan — yaitu, hingga beberapa bulan yang lalu, ketika Kelompok Kerja Komponen Web mengusulkan bahwa <link rel=“stylesheet”> harus berfungsi DOM bayangan. Setelah hanya seminggu berdiskusi, mereka semua setuju bahwa mereka harus melakukannya, dan beberapa hari kemudian mereka menambahkannya ke spesifikasi HTML.

 <template> <link rel="stylesheet" href="styleguide.css"> <style> .container { max-width: 300px; padding: 50px; border: 1px solid grey; } .footnote { text-align: center; } </style> <!-- rest of template DOM --> </template>

Jika kedengarannya agak terlalu cepat bagi kelompok kerja untuk menyepakati suatu spesifikasi, itu karena itu bukan proposal baru. Membuat tag link berfungsi di shadow DOM sebenarnya telah diusulkan setidaknya tiga tahun lalu, tetapi ditunda sampai mereka dapat memastikan bahwa itu tidak menjadi masalah untuk kinerja.

Jika penerimaan proposal tidak cukup menarik, Chrome 55 (saat ini Chrome Canary) menambahkan fungsionalitas awal untuk membuat tag link berfungsi di shadow DOM. Bahkan tampaknya fungsi ini telah mendarat di versi Chrome saat ini. Bahkan Safari telah mengimplementasikan fitur tersebut di Safari 18.

Mampu menautkan dalam gaya bersama sejauh ini merupakan metode yang paling nyaman untuk berbagi gaya antar komponen web. Yang harus Anda lakukan adalah membuat tag link , dan semua elemen asli akan diberi gaya yang sesuai, tanpa memerlukan pekerjaan tambahan.

Tentu saja, cara pembuat browser mengimplementasikan fitur tersebut akan menentukan apakah solusi ini layak. Agar ini berfungsi dengan baik, tag link perlu dihapus duplikatnya, sehingga beberapa komponen web yang meminta file CSS yang sama hanya akan menyebabkan satu permintaan HTTP. CSS juga perlu diuraikan hanya sekali, sehingga setiap instance komponen web tidak perlu menghitung ulang gaya yang dibagikan, tetapi akan menggunakan kembali gaya yang dihitung.

Chrome sudah melakukan keduanya. Jadi, jika semua pembuat browser lain menerapkannya dengan cara yang sama, maka tag link yang bekerja di shadow DOM pasti akan memecahkan masalah tentang cara berbagi gaya antar komponen web.

Lembar Gaya yang Dapat Dibangun

Anda mungkin merasa sulit untuk percaya, karena kami bahkan belum mendapatkannya, tetapi tag link yang berfungsi di shadow DOM bukanlah solusi jangka panjang. Sebaliknya, ini hanya solusi jangka pendek untuk membawa kita ke solusi nyata: lembar gaya yang dapat dibangun.

Lembar gaya yang dapat dibangun adalah proposal untuk memungkinkan pembuatan objek StyleSheet dalam JavaScript melalui fungsi konstruktor. Lembar gaya yang dibuat kemudian dapat ditambahkan ke shadow DOM melalui API, yang memungkinkan shadow DOM untuk menggunakan serangkaian gaya bersama.

Sayangnya, hanya ini yang bisa saya kumpulkan dari proposal. Saya mencoba mencari informasi lebih lanjut tentang apa yang dimaksud dengan lembar gaya yang dapat dibangun dengan bertanya kepada Kelompok Kerja Komponen Web, tetapi mereka mengarahkan saya ke milis Kelompok Kerja CSS W3C, di mana saya bertanya lagi, tetapi tidak ada yang menjawab. Saya bahkan tidak tahu bagaimana proposal itu berkembang, karena belum diperbarui selama lebih dari dua tahun.

Meski begitu, Kelompok Kerja Komponen Web menggunakannya sebagai solusi untuk berbagi gaya antar komponen web. Mudah-mudahan, proposal akan diperbarui atau Kelompok Kerja Komponen Web akan merilis lebih banyak informasi tentangnya dan adopsinya. Sampai saat itu, solusi "jangka panjang" sepertinya tidak akan terjadi di masa mendatang.

Pelajaran yang Dipetik

Setelah berbulan-bulan penelitian dan pengujian, saya cukup berharap untuk masa depan. Sangat menyenangkan mengetahui bahwa setelah bertahun-tahun tidak memiliki solusi untuk berbagi gaya antar komponen web, akhirnya ada jawaban. Jawaban-jawaban itu mungkin tidak akan ditetapkan untuk beberapa tahun lagi, tetapi setidaknya mereka ada di sana.

Jika Anda ingin menggunakan panduan gaya bersama untuk menata komponen web hari ini, Anda tidak dapat menggunakan shadow DOM dan sebagai gantinya membuat elemen khusus, atau Anda dapat menggunakan pustaka komponen web yang mendukung polifill untuk berbagi gaya. Kedua solusi memiliki pro dan kontra, jadi gunakan mana yang paling sesuai untuk proyek Anda.

Jika Anda memutuskan untuk menunggu beberapa saat sebelum mempelajari komponen web, maka dalam beberapa tahun kita akan memiliki beberapa solusi hebat untuk berbagi gaya di antara mereka. Jadi, terus periksa kembali bagaimana perkembangannya.

Hal yang Perlu Diingat

Ingatlah beberapa hal jika Anda memutuskan untuk menggunakan elemen kustom atau komponen web hari ini.

Yang terpenting, spesifikasi komponen web masih aktif dikembangkan, yang berarti bahwa segala sesuatunya dapat dan akan berubah. Komponen web masih merupakan ujung tombak, jadi bersiaplah untuk tetap waspada saat Anda mengembangkannya.

Jika Anda memutuskan untuk menggunakan shadow DOM, ketahuilah bahwa itu cukup lambat dan tidak berkinerja baik di browser polyfilled. Karena alasan inilah pengembang Polymer membuat implementasi DOM yang teduh dan menjadikannya sebagai default.

Chrome, Opera dan, baru-baru ini, Safari adalah satu-satunya browser yang mendukung shadow DOM versi 0. Firefox masih dalam pengembangan, meskipun telah mendukungnya di belakang percobaan sejak versi 29. Microsoft masih mempertimbangkannya untuk Edge dan menjadikannya sebagai prioritas tinggi pada peta jalannya.

Namun, shadow DOM versi 0 adalah spesifikasi lama. Shadow DOM versi 1 adalah yang baru, dan hanya Chrome, Safari, dan Opera yang sepenuhnya mendukungnya. Belum lagi bahwa elemen kustom versi 0 mengalami peningkatan yang sama, dan hanya Chrome yang sepenuhnya mendukung elemen kustom versi 1, sedangkan pratinjau teknis Safari mendukungnya pada versi 17. Elemen kustom versi 1 memiliki beberapa perubahan besar dalam cara komponen web ditulis, jadi pastikan untuk sepenuhnya memahami apa yang diperlukan.

Terakhir, polyfill webcomponentjs hanya mendukung implementasi versi 0 dari shadow DOM dan elemen kustom. Cabang versi 1 dari polyfill akan mendukung versi 1, tetapi belum dirilis.