Simpan token desain bersama di CSS halaman, sediakan variabel khusus komponen sebagai API penataan gaya, dan hubungkan keduanya dengan pemetaan kecil yang dikelola halaman. Tutorial ini membuat demo Mac lokal yang memisahkan tanggung jawab tersebut.

Apa yang menjadi tanggung jawab halaman, dan apa yang menjadi tanggung jawab komponen?

Bagi seseorang yang mengedit halaman web buatan sendiri di Mac, tugas konkretnya adalah memberi tema pada komponen yang dapat digunakan kembali tanpa membuat implementasinya bergantung pada nama token halaman. Contoh di bawah menggunakan komponen orbit-tile sintetis yang berisi bentuk abstrak dan label pendek.

Token desain dan variabel publik komponen sama-sama dapat berupa properti kustom CSS. Perbedaannya terletak pada kontrak yang Anda dokumentasikan. Properti kustom biasa yang tidak terdaftar berpartisipasi dalam kaskade dan diwariskan; mendeklarasikannya pada :root membuatnya tersedia melalui pewarisan di seluruh dokumen. Tidak ada kata kunci CSS khusus yang menjadikan suatu properti sebagai token desain. Menggunakan properti kustom CSS (variabel)

Gunakan tabel kepemilikan ini untuk menentukan tempat deklarasi. Nama-namanya hanya contoh dan berlaku lokal untuk contoh ini.

Lapisan Contoh Tanggung jawab
Token desain halaman --scene-accent, --scene-rounding Pilihan visual bersama untuk halaman buatan sendiri
Aturan integrasi halaman Aturan yang menargetkan orbit-tile Menerjemahkan pilihan halaman ke API komponen
Variabel publik komponen --orbit-tile-fill, --orbit-tile-radius Kontrol terdokumentasi yang tersedia bagi konsumen
Implementasi komponen .shape, aturan tata letak, nilai bawaan literal Merender komponen tanpa memerlukan token halaman

Uji portabilitas berguna: apakah halaman lain dapat menyediakan nama token yang berbeda sambil menggunakan komponen yang sama tanpa perubahan? Dengan pemetaan yang dikelola halaman, bisa. Halaman baru itu akan memetakan tokennya sendiri ke variabel publik komponen yang sama.

Bagaimana kontrak penataan gaya melewati Shadow DOM?

Shadow DOM memisahkan pencocokan selektor dari pewarisan. Selektor halaman biasanya tidak dapat memilih bentuk internal yang berada di balik batas shadow. Namun, nilai properti yang diwariskan tetap dapat mencapainya melalui host. Spesifikasi CSS Shadow menjelaskan pohon elemen datar yang digunakan untuk hubungan ini; pohon selektor yang terpisah tidak menghilangkan pewarisan. CSS Shadow Module Level 1

Biarkan variabel publik tidak ditetapkan di dalam komponen dan berikan nilai bawaan di tempat variabel tersebut digunakan. Misalnya, background-color: var(--orbit-tile-fill, #667085) menerima nilai warisan dari konsumen sekaligus menyediakan nilai bawaan mandiri. Sebaliknya, mendeklarasikan --orbit-tile-fill: #667085 pada :host akan memberi host nilai tersendiri dan menghalangi nilai warisan dari leluhur. Konsumen tetap dapat menargetkan host secara langsung. Menata gaya Web Components

Untuk contoh ini, dokumentasikan hanya dua kontrol publik:

Variabel publik Nilai yang diterima untuk contoh ini Nilai bawaan jika tidak ada Efek
--orbit-tile-fill Warna CSS yang valid #667085 Warna latar belakang bentuk
--orbit-tile-radius Satu panjang atau persentase nonnegatif 1rem Radius sudut bentuk

Nilai yang diterima ini merupakan kesepakatan API. Implementasi dasar tidak mendaftarkan atau memvalidasinya secara otomatis. Nama kelas internal adalah detail implementasi, jadi penulis halaman sebaiknya menyesuaikan variabel publik alih-alih bergantung pada .shape.

Buat contoh lokal lengkap di Mac Anda

Gunakan editor teks biasa dan browser yang mendukung properti kustom CSS, Shadow DOM, dan elemen kustom otonom. Contoh ini menggunakan elemen otonom yang memperluas HTMLElement; MDN membedakan pendekatan itu dari elemen bawaan yang dikustomisasi, yang tidak direncanakan untuk didukung Safari. Menggunakan elemen kustom

Di TextEdit, pilih File > New, lalu Format > Make Plain Text. Tempelkan seluruh dokumen di bawah dan simpan sebagai token-demo.html. Jika diminta, pilih Use .html. Saat membukanya kembali untuk diedit, pilih Ignore rich text commands pada dialog buka, atau aktifkan Display HTML files as HTML code instead of formatted text di pengaturan. Menggunakan dokumen HTML di TextEdit pada Mac

Stylesheet pertama dokumen mengelola token, aturan integrasi, dan tata letak halaman. Komponen membuat stylesheet terpisah di dalam root shadow-nya. HTML mendefinisikan elemen style sebagai cara untuk menyematkan CSS; menempatkan seluruh sumber dalam satu file membuat pengaturan sumber daya contoh ini tetap jelas. Standar HTML: Elemen style

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Orbit tile token demo</title>
  <style>
    /* Page-owned shared tokens */
    :root {
      --scene-accent: #4058b8;
      --scene-rounding: 12px;
    }

    /* Page-owned integration mapping */
    orbit-tile {
      --orbit-tile-fill: var(--scene-accent);
      --orbit-tile-radius: var(--scene-rounding);
    }

    /* A local page theme */
    .alternate {
      --scene-accent: #276f64;
      --scene-rounding: 24px;
    }

    /* An intentional override for one component instance */
    orbit-tile.special {
      --orbit-tile-fill: #a65b20;
      --orbit-tile-radius: 50%;
    }

    body {
      max-width: 36rem;
      margin: 3rem auto;
      padding: 0 1rem;
      font: 1rem/1.5 system-ui, sans-serif;
    }
    main { display: grid; gap: 1rem; }
  </style>
</head>
<body>
  <main>
    <orbit-tile>Sample A</orbit-tile>
    <section class="alternate" aria-label="Alternate samples">
      <orbit-tile>Sample B</orbit-tile>
    </section>
    <orbit-tile class="special">Sample C</orbit-tile>
  </main>

  <script>
    class OrbitTile extends HTMLElement {
      constructor() {
        super();
        const root = this.attachShadow({ mode: 'open' });
        const style = document.createElement('style');
        style.textContent = `
          :host { display: block; }
          .tile {
            display: flex;
            align-items: center;
            gap: 1rem;
            padding: 1rem;
            background: #f2f4f6;
            color: #202630;
          }
          .shape {
            display: block;
            width: 4rem;
            height: 4rem;
            flex: 0 0 4rem;
            background-color: var(--orbit-tile-fill, #667085);
            border-radius: var(--orbit-tile-radius, 1rem);
          }
        `;
        const tile = document.createElement('div');
        tile.className = 'tile';
        const shape = document.createElement('span');
        shape.className = 'shape';
        shape.setAttribute('aria-hidden', 'true');
        tile.append(shape, document.createElement('slot'));
        root.append(style, tile);
      }
    }
    customElements.define('orbit-tile', OrbitTile);
  </script>
</body>
</html>

Buka file yang disimpan di Safari, Chrome, atau Firefox. Contoh ini tidak menggunakan skrip, font, gambar, atau stylesheet eksternal. JavaScript telah lolos pemeriksaan sintaks; hasil visual berikut adalah hasil yang diharapkan berdasarkan deklarasinya, bukan laporan eksekusi browser.

Instans Bentuk yang diharapkan Jalur nilai
Sample A Biru, dengan sudut 12px Token root → pemetaan host → komponen
Sample B Hijau, dengan sudut 24px Token bagian → pemetaan host → komponen
Sample C Lingkaran jingga Override instans → komponen

Perhatikan bahwa JavaScript komponen tidak memuat referensi --scene-*. Stylesheet-nya hanya menggunakan nama publik --orbit-tile-*. Halaman dapat menata ulang kosakata temanya tanpa mengubah komponen.

Di mana pemetaan token ke komponen sebaiknya dilakukan?

Petakan nilai di tempat tema yang dimaksud tersedia. Dalam demo ini, aturan orbit-tile diterapkan pada setiap host. Dengan demikian, host kedua menyelesaikan --scene-accent setelah mewarisi nilai hijau dari bagian tersebut.

Hindari memindahkan pemetaan itu ke :root tanpa mempertimbangkan waktu penyelesaiannya. Jika --orbit-tile-fill: var(--scene-accent) dihitung di sana, turunannya mewarisi nilainya yang sudah terselesaikan. Mengubah hanya --scene-accent pada bagian berikutnya tidak membangun ulang alias yang diwariskan. Referensi var() pada properti kustom diselesaikan sebelum nilai hitungannya diwariskan. Modul Properti Kustom CSS untuk Variabel Kaskade Level 1

Pertimbangan praktisnya adalah cakupan: gunakan pemetaan pada host saat setiap instans harus mengikuti token halaman di sekitarnya. Jika seluruh wilayah memang dimaksudkan untuk berbagi satu nilai komponen publik, mendeklarasikan variabel publik itu pada wilayah tersebut dapat sesuai, tetapi hapus pemetaan host untuk variabel itu agar tidak menggantikan nilai warisannya.

Untuk penggunaan internal yang berulang, alias implementasi dapat menyatukan deklarasi fallback. Nama seperti --_orbit-tile-fill dapat menandakan konvensi internal, tetapi garis bawah tidak menciptakan privasi yang diberlakukan. Penggunaan langsung, seperti pada contoh lengkap, lebih mudah diikuti saat setiap nilai hanya digunakan sekali. Menata gaya Web Components

Bagaimana cara mendiagnosis override yang tidak berfungsi?

Gunakan tiga instans sebagai uji kontrak sederhana. Ubah satu deklarasi setiap kali, simpan, lalu muat ulang. Pemeriksaan ini membantu membedakan sumber daya yang hilang, masalah pewarisan, dan nilai yang tidak valid.

  1. Ubah aksen root menjadi #7251a1. Hanya Sample A yang diharapkan berubah; bagian dan instans memiliki pilihan masing-masing.
  2. Ubah aksen bagian menjadi #32758a. Sample B diharapkan berubah tanpa mengedit kode komponen.
  3. Hapus seluruh pemetaan integrasi. Sample A dan Sample B diharapkan menggunakan isian abu-abu dan radius 1rem bawaan komponen; Sample C tetap memakai override publik eksplisitnya.
  4. Pulihkan pemetaan sebelum melanjutkan eksperimen lain.

Jika semua bentuk menghilang, periksa terlebih dahulu apakah dokumen disimpan sebagai HTML dan skripnya masih utuh. Jika label muncul tetapi bentuk tidak memiliki gaya, periksa stylesheet komponen. Stylesheet dokumen saja tidak menata turunan shadow dengan selektor biasa; implementasi harus memasang gaya internalnya ke pohon shadow. MDN mendokumentasikan gaya tertanam dan stylesheet yang dibuat untuk tujuan tersebut. Menggunakan shadow DOM

Jika hanya override leluhur yang gagal, cari deklarasi variabel publik langsung pada host. Dalam contoh ini, pemetaan integrasi adalah deklarasi semacam itu. Ubah token halaman yang menjadi sumbernya, timpa variabel publik pada instans, atau hapus pemetaan jika kontrak yang diinginkan adalah pemberian tema publik dari tingkat leluhur.

Jika bentuk menjadi transparan setelah menetapkan --orbit-tile-fill: 12px, fallback tidak akan memperbaikinya. Variabelnya ada, tetapi nilai substitusinya tidak valid untuk background-color. Deklarasi itu menjadi tidak valid pada waktu nilai dihitung; CSS tidak kembali ke deklarasi latar belakang sebelumnya. Hapus penetapan tersebut atau berikan warna yang valid. Modul Properti Kustom CSS untuk Variabel Kaskade Level 1

Haruskah variabel publik menggunakan @property?

Pendaftaran bersifat opsional untuk kontrak ini. @property menambahkan batasan sintaks, nilai awal, dan perilaku pewarisan yang eksplisit. MDN menandainya Baseline 2024, tersedia di berbagai browser terkini sejak Juli 2024, sekaligus memperingatkan bahwa browser lama mungkin tidak mendukungnya. Contoh lengkap ini tidak menjadikan pendaftaran sebagai prasyarat. Aturan CSS @property

Jika Anda menerapkan pendaftaran, koordinasikan pada tingkat dokumen. Dokumentasi implementasi Chrome melaporkan bahwa pendaftaran di dalam root shadow diabaikan; laporan itu bertanggal Agustus 2024, jadi anggaplah sebagai batas interoperabilitas yang terdokumentasi, bukan bukti pengujian browser baru-baru ini. Jalur yang didukung dan dijelaskan di sana adalah pendaftaran pada cakupan dokumen, dengan komponen menggunakan properti tersebut melintasi batas. Nama CSS yang ditentukan penulis dan shadow DOM: Dalam spesifikasi dan praktiknya

Pendaftaran juga mengubah perilaku. Menetapkan inherits: false akan merusak pewarisan dari host ke bentuk pada contoh ini. Warna awal yang terdaftar berarti properti yang tidak ditetapkan akan memiliki warna itu, sehingga fallback var() yang digunakan bukan lagi nilai bawaan saat nilai tidak tersedia. Pertahankan inherits: true untuk rancangan ini dan tentukan dengan sengaja mekanisme mana yang mengelola nilai bawaan. Aturan CSS @property

Kontrak akhir harus memungkinkan penulis halaman menjelaskan jalur setiap nilai: pilihan bersama halaman, pemetaan ke kontrol komponen yang terdokumentasi, lalu fallback yang dikelola komponen. Letakkan pemetaan dekat dengan cakupan tema yang dituju, biarkan masukan publik yang diwariskan tetap tidak ditetapkan secara internal, dan pertahankan contoh tiga instans setiap kali Anda memperbarui API.

Sumber