Di Solid, tampilan elemen diatur lewat tiga prop: class untuk kelas CSS yang tetap, classList untuk kelas yang nyala-mati mengikuti kondisi, dan style untuk nilai CSS yang dihitung. Bayangin kartu buku di rak Toko Buku Kak Nadia. Semua kartu memakai bingkai yang sama, itu kelas tetapnya. Begitu sebuah buku habis, Kak Nadia menjepitkan stiker abu-abu habis di kartunya, dan mencabutnya lagi saat stok datang. Kartunya gak dicat ulang. Dia cuma menjepit atau mencabut satu stiker. classList adalah kumpulan saklar stiker itu: satu saklar per nama kelas, masing-masing mengikuti satu kondisi.
🧪 Tebakan cepat: kartu Cantik Itu Luka (stok 0) ditulis dengan
class={"kartu " + tema()}danclassList={{ habis: stok() === 0 }}, jadi tampil abu-abu. Lalu tema diganti dariterangkegelap. Kartunya masih abu-abu atau gak? Jawabannya ada di bagian "class dan classList di elemen yang sama".
class: kelas yang tetap
<div class="kartu">...</div>
Sama seperti di HTML, dan Solid menulisnya langsung ke template. Nilainya juga boleh dihitung: class={stok() === 0 ? "kartu habis" : "kartu"}. Tiap kali hasilnya berubah, Solid mengganti seluruh atribut: el.className = "kartu habis". Untuk satu kondisi ini masih rapi. Dengan dua, tiga kondisi, string-nya jadi susah dibaca.
classList: kelas yang nyala-mati
Kartu buku Toko Buku Kak Nadia, dengan stoknya sendiri:
import { createSignal } from "solid-js"
function KartuBuku(props) {
const [stok, setStok] = createSignal(props.stokAwal)
return (
<div class="kartu" classList={{ habis: stok() === 0, "sisa-sedikit": stok() > 0 && stok() < 3 }}>
<h3>{props.judul}</h3>
<p class="harga" style={{ "text-decoration": stok() === 0 ? "line-through" : "none" }}>Rp{props.harga}</p>
<p>Stok: {stok()}</p>
<button onClick={() => setStok(s => s - 1)} disabled={stok() === 0}>Beli 1</button>
</div>
)
}
Dengan CSS .habis { opacity: 0.5; filter: grayscale(1) } dan .sisa-sedikit { border-color: #f59e0b }, kartu Bumi Manusia (stok awal 2) berubah begini:
| Kejadian | stok() |
Atribut class |
|---|---|---|
| Halaman dibuka | 2 | kartu sisa-sedikit |
Klik Beli 1 |
1 | kartu sisa-sedikit |
Klik Beli 1 lagi |
0 | kartu habis, kartunya abu-abu |
classListmenerima objek{ namaKelas: kondisi }. Kelasnya menempel selama kondisinya benar, dan lepas saat kondisinya salah.- Nama kelas yang ada tanda
-ditulis di dalam kutip:"sisa-sedikit". - Kondisinya ditulis sebagai pemanggilan,
stok() === 0, supaya dibaca ulang tiap stoknya berubah. - Compiler Solid 1.9 mengubahnya jadi satu baris per kelas:
el.classList.toggle("habis", stok() === 0). Kelas lain di elemen itu, termasukkartu, gak disentuh.
Ini latihan pelajaran ini: sebuah <div>Konten</div> memakai classList={{ active: active() }}, signal-nya mulai dari true, dan tombol Toggle menjalankan setActive(v => !v). Klik pertama melepas kelas active, klik kedua memasangnya lagi.
style: objek dengan key kebab-case
style menerima objek. Key-nya nama properti CSS asli, kebab-case dalam kutip, persis seperti di file CSS:
<p style={{ "text-decoration": stok() === 0 ? "line-through" : "none", "font-size": "18px" }}>Rp{props.harga}</p>
- Solid memasang tiap key dengan
el.style.setProperty("text-decoration", nilai). Harga Cantik Itu Luka jadi dicoret. setPropertycuma mengenal nama CSS. Key camelCase dari kebiasaan React,textDecorationataubackgroundColor, dibuang browser tanpa error. Diuji di Solid 1.9:style={{ backgroundColor: "red" }}gak mewarnai apa pun.- Angka tanpa satuan juga dibuang:
"font-size": 20gak berlaku, tulis"18px". Yang boleh angka polos cuma properti tanpa satuan, sepertiopacity: 0.5. stylejuga boleh string biasa:style={`opacity: ${stok() === 0 ? 0.5 : 1}`}.
class dan classList di elemen yang sama
Kartu dengan kelas tema yang dihitung, plus classList:
<div class={"kartu " + tema()} classList={{ habis: stok() === 0 }}>
Hasilnya di Solid 1.9, untuk Cantik Itu Luka (stok 0):
| Kejadian | Yang dijalankan | Atribut class |
|---|---|---|
| Halaman dibuka | className = "kartu terang", lalu toggle("habis", true) |
kartu terang habis |
Tema diganti ke gelap |
className = "kartu gelap" |
kartu gelap |
Kartunya gak abu-abu lagi, padahal stoknya masih 0. Itu jawaban tebakannya. class yang dihitung mengganti seluruh atribut dan ikut menghapus habis. classList cuma bertindak saat kondisinya sendiri berubah, dan stok() === 0 masih true seperti sebelumnya, jadi gak ada yang memasangnya lagi. Aturannya: kalau satu elemen memakai classList, biarkan class-nya tetap, dan pindahkan kelas yang berubah ke classList: class="kartu" classList={{ habis: stok() === 0, gelap: tema() === "gelap" }}.
CSS Modules: nama kelas yang gak bentrok
Kalau KartuBuku dan Keranjang sama-sama punya .judul di file CSS masing-masing, aturan yang dimuat belakangan menimpa yang lain, karena semua kelas CSS biasa berlaku di seluruh halaman. CSS Modules mencegahnya: file berakhiran .module.css diimpor sebagai objek, dan tiap nama kelasnya diganti jadi nama unik.
import styles from "./KartuBuku.module.css"
<div class={styles.kartu} classList={{ [styles.habis]: stok() === 0 }}>
Vite (bundler yang dipakai proyek Solid) mengganti .kartu jadi nama seperti _kartu_1x8p2_1, dan styles.kartu berisi nama itu. Jadi scope nama kelasnya otomatis per file. Ini fitur bundler, jadi berjalan di proyek Vite, bukan di Playground.
⚠️ Jebakan yang sering ketemu
- Kondisi dibaca sekali.
const habis = stok() === 0di badan komponen laluclassList={{ habis }}: komponen jalan sekali, jadi nilainya macet. Tulis pemanggilannya langsung di objek:classList={{ habis: stok() === 0 }}. classyang dihitung bersamaclassList. Tiapclassberubah, kelas dariclassListikut terhapus. Pakaiclassyang tetap.- Key camelCase atau angka tanpa satuan di
style.backgroundColor,fontSize,"font-size": 20dibuang tanpa pesan error. Tulis"background-color","font-size": "18px". - Tombolnya gak persis
Toggle, atau cuma mengubah sekali. Latihan ini mengklik tombol bertulisanTogglesekali (kelasactiveharus hilang), lalu dua kali dari awal (kelasnya harus kembali).setActive(false)cuma berhasil di klik pertama. PakaisetActive(v => !v).
TL;DR: class="kartu" untuk kelas tetap. classList={{ habis: stok() === 0 }} untuk kelas yang nyala-mati, satu classList.toggle per kelas, kondisinya ditulis sebagai pemanggilan. style={{ "text-decoration": "line-through", opacity: 0.5 }} dengan key kebab-case dalam kutip dan satuan di nilainya; backgroundColor dan "font-size": 20 dibuang browser. Jangan campur class yang dihitung dengan classList di satu elemen: tiap class berubah, kelas dari classList hilang. CSS Modules (import styles from "./KartuBuku.module.css") membuat nama kelas unik per file, jadi gak bentrok dengan komponen lain.