Materi : CSS (Cascading Style Sheets)
Topik : Selector, Cascade, Box Model, Typography, Positioning, Flexbox, Grid, Media Query, Responsive Design
1. Pendahuluan: Apa itu CSS dan Kenapa Kita Butuh CSS?
HTML bertugas membangun struktur dan konten halaman (heading, paragraf, gambar, tombol, dll). Tapi HTML sendiri tidak tahu bagaimana elemen-elemen itu harus terlihat.
Coba bayangkan tanpa CSS : semua halaman web di dunia ini akan terlihat seperti dokumen teks polos font default, warna hitam-putih, semua elemen tersusun dari atas ke bawah tanpa tata letak. CSS (Cascading Style Sheets) adalah bahasa yang memberi "wajah" pada struktur HTML tersebut: warna, jarak, ukuran, posisi, animasi, hingga tata letak responsif di berbagai ukuran layar.
Analogi sederhana :
- HTML = kerangka rumah (dinding, pintu, jendela)
- CSS = interior desain (cat, lantai, furniture, pencahayaan)
Cara Menghubungkan CSS ke HTML
Ada 3 cara, tapi hanya 1 yang jadi best practice :
|
Cara |
Contoh |
Kapan dipakai |
|---|---|---|
Inline |
|
Hindari — susah dikelola, spesifisitas tinggi |
Internal |
|
Untuk contoh cepat / prototipe kecil |
External (disarankan) |
|
Untuk proyek nyata — bisa dipakai ulang di banyak halaman, gampang di-maintain |
Kenapa external lebih disarankan? Karena memisahkan concern (struktur vs tampilan), file bisa di-cache browser (loading lebih cepat di kunjungan berikutnya), dan satu file CSS bisa dipakai di puluhan halaman HTML sekaligus.
2. Selector CSS
Selector adalah "penunjuk" atau cara kita memilih elemen HTML mana yang ingin diberi style.
2.1 Selector Dasar
Kapan pakai class vs id?
class→ dipakai berkali-kali, untuk styling yang reusable (misalnya semua tombol punya class.btn)id→ hanya boleh 1 kali per halaman, biasanya dipakai untuk target JavaScript atau anchor link, bukan untuk styling utama karena spesifisitasnya terlalu tinggi dan sulit di-override
2.2 Selector Kombinasi
Kenapa penting membedakan nav a dan nav > a? Kalau struktur HTML-mu bersarang dalam (misalnya <nav><ul><li><a>), nav > a tidak akan mengenai <a> tersebut karena bukan anak langsung. Salah pilih combinator = style tidak muncul, dan ini salah satu bug paling umum pemula.
2.3 Pseudo-class dan Pseudo-element
Jika tidak menggunakan pseudo-class, kamu terpaksa menambahkan/menghapus class lewat JavaScript hanya untuk efek hover atau styling baris genap-ganjil pada tabel padahal browser sudah menyediakan mekanisme bawaan yang lebih ringan dan tanpa JavaScript sama sekali.
2.4 Attribute Selector
Berguna saat elemen tidak punya class tapi bisa dibedakan dari atributnya, misalnya membedakan <input type="text"> dan <input type="checkbox"> tanpa menambah class manual di HTML.
3. Cascade & Specificity (Kenapa CSS Kadang "Tidak Ngaruh"?)
Ini adalah bagian yang paling sering membingungkan pemula: kenapa style yang saya tulis tidak muncul, padahal tidak ada error?
Jawabannya ada pada 3 konsep: Cascade, Specificity, dan Source Order.
3.1 Cascade (Urutan Prioritas)
Ketika ada beberapa aturan yang bentrok pada elemen yang sama, browser menentukan pemenang berdasarkan urutan:
- Importance -
!importantmenang di atas segalanya (tapi sebaiknya dihindari) - Specificity - selector yang lebih spesifik menang
- Source order - kalau specificity sama, aturan yang ditulis paling akhir yang menang
3.2 Specificity (Bobot Selector)
Setiap selector punya "skor". Semakin spesifik, semakin tinggi skornya:
|
Selector |
Skor (id, class, element) |
Contoh |
|---|---|---|
Element |
0-0-1 |
|
Class / attribute / pseudo-class |
0-1-0 |
|
ID |
1-0-0 |
|
Inline style |
tertinggi |
|
Kenapa harus paham ini? Kalau tidak paham cascade, pemula biasanya akan "menyerah" dan menyelesaikan masalah dengan menambahkan !important di mana-mana. Ini anti-pattern: begitu satu !important dipakai, style lain butuh !important juga untuk override, dan akhirnya CSS jadi tidak terkontrol dan sangat sulit di-maintain. Memahami specificity artinya kamu bisa menulis selector yang "cukup spesifik" tanpa perlu senjata pamungkas itu.
4. Box Model
Setiap elemen HTML pada dasarnya adalah sebuah kotak (box), tersusun dari 4 lapisan:
4.1 Masalah Klasik : content-box vs border-box
Secara default, width di CSS hanya mengatur content, bukan total lebar kotak. Ini sering bikin bingung:
Pemula sering berencana membuat 3 kolom @300px pas 1 baris (900px), tapi ternyata meleber jadi 1050px dan malah turun ke baris baru inilah akibat tidak paham box model.
Solusi standar industri:
Dengan border-box, width: 300px sudah termasuk padding dan border di dalamnya — jadi lebar total kotak pasti 300px. Inilah alasan hampir semua CSS reset/framework modern (Bootstrap, Tailwind) langsung set box-sizing: border-box di awal.
4.2 Margin Collapsing
Satu perilaku "aneh" yang wajib diketahui: margin vertikal antar elemen sibling tidak dijumlahkan, melainkan diambil yang terbesar.
Ini sering membuat pemula bingung kenapa jarak antar elemen "tidak nambah" walau margin sudah ditambah dua-duanya.
5. Typography
Typography menentukan keterbacaan dan kenyamanan visual teks di halaman.
5.1 Kenapa Selalu Sediakan Font Fallback?
font-family: "Segoe UI", Arial, sans-serif; daftar ini adalah urutan prioritas. Jika font pertama tidak tersedia di device pengguna (misalnya user pakai Linux/HP tanpa font tersebut ter-install), browser otomatis pindah ke font berikutnya. Jika tidak diberi fallback, dan font utama gagal dimuat, browser akan menggunakan font default yang tidak konsisten antar device.
5.2 Satuan Ukuran: px vs em vs rem
|
Satuan |
Sifat |
Kapan dipakai |
|---|---|---|
|
Absolut, tetap |
Border, shadow, elemen kecil yang tidak perlu scaling |
|
Relatif ke font-size parent |
terdekat Bisa "menumpuk" (compounding) — hati-hati |
|
Relatif ke font-size root (html) |
Disarankan untuk font-size, spacing, agar konsisten dan mudah diskalakan |
Kenapa rem lebih disukai daripada px untuk font? Karena rem menghormati pengaturan aksesibilitas browser pengguna (misalnya user memperbesar font default browser untuk kenyamanan mata). Kalau kamu memaksa px, ukuran teks di layar user akan tetap kaku sebesar itu mengabaikan preferensi aksesibilitas mereka. rem juga membuat perubahan skala global jadi mudah: cukup ubah font-size di html, seluruh elemen yang pakai rem ikut menyesuaikan proporsional.
Kenapa em bisa berbahaya? Karena bersifat relatif ke parent, jika elemen bersarang dalam (nested), ukurannya bisa "membengkak" tanpa disadari:
6. Positioning
Property position menentukan bagaimana elemen ditempatkan relatif terhadap elemen lain.
|
Nilai |
Perilaku |
Contoh Penggunaan |
|---|---|---|
|
Default, tidak bisa diatur |
Elemen biasa |
|
Bergeser dari posisi aslinya, tapi tetap "menyisakan ruang" di layout asal |
Membuat elemen jadi referensi untuk child |
|
Keluar dari alur dokumen, posisi mengikuti ancestor terdekat yang |
Badge notifikasi, dropdown menu, tooltip |
|
Posisi tetap relatif ke viewport, tidak ikut scroll |
Tombol "back to top", navbar melayang |
|
Bertingkah seperti |
Header tabel, navbar yang menempel saat discroll |
6.1 Konsep Kunci: "Positioning Context"
absolute selalu mencari ancestor terdekat yang punya position selain static sebagai acuan. Kalau tidak ketemu, acuannya adalah <html> (viewport dokumen).
Jika .card tidak diberi position: relative, maka .badge akan mencari ancestor lain di atasnya bisa jadi melompat ke pojok kanan atas seluruh halaman, bukan pojok kartu. Ini salah satu bug positioning paling umum: lupa memberi position: relative pada parent.
7. Flexbox
Flexbox dirancang untuk mengatur elemen dalam satu dimensi baris (row) atau kolom (column).
7.1 Kenapa Flexbox Ada? (Masalah Sebelum Flexbox)
Sebelum Flexbox populer (sekitar 2015-an), developer membuat layout dengan float atau display: inline-block, yang punya banyak masalah:
- Elemen
floatkeluar dari alur normal, sehingga parent-nya bisa "collapse" (tinggi jadi 0) perlu trikclearfix - Centering vertikal itu sangat sulit tanpa Flexbox (butuh trik
position+transform, atau tabel)
Dengan Flexbox, centering elemen secara vertikal & horizontal cukup:
Jika tidak menggunakan Flexbox untuk kasus seperti navbar (logo di kiri, menu di kanan, sejajar vertikal), kamu harus menghitung posisi manual dengan position: absolute dan margin, yang rapuh terhadap perubahan ukuran konten.
7.2 Properti Kunci
Pada container (parent):
justify-content- mengatur sumbu utama (main axis)align-items- mengatur sumbu silang (cross axis)flex-wrap- apakah item boleh pindah baris jika ruang tidak cukup
Pada item (child):
flex-grow- seberapa besar item "menyerap" ruang kosongflex-shrink- seberapa besar item boleh menyusutflex-basis- ukuran awal sebelum grow/shrink dihitung
8. CSS Grid
Grid dirancang untuk mengatur elemen dalam dua dimensi sekaligus baris dan kolom.
8.1 Kenapa Grid Dibutuhkan Kalau Sudah Ada Flexbox?
Flexbox itu satu dimensi kalau kamu punya banyak baris, setiap baris "tidak tahu-menahu" ukuran kolom di baris lain, sehingga kolom antar baris tidak otomatis sejajar kecuali diatur manual dengan trik tambahan.
Coba bayangkan membuat layout galeri foto atau dashboard dengan banyak baris & kolom yang harus sejajar rapi dengan Flexbox kamu harus membungkus banyak div bersarang dan menghitung lebar manual. Dengan Grid, cukup definisikan struktur kolom & baris sekali di parent, lalu setiap item otomatis menempati sel gridnya, bahkan bisa melintasi beberapa kolom/baris sekaligus (grid-column: span 2).
Grid juga mendukung template area yang sangat deskriptif:
Bandingkan dengan cara lama (float/table layout) yang butuh markup HTML tambahan hanya demi keperluan visual Grid memisahkan struktur visual dari struktur HTML, sehingga HTML tetap semantik.
8.2 Flexbox vs Grid: Kapan Pakai yang Mana?
Ini pertanyaan yang sering ditanyakan oleh pemula:
|
Aspek |
Flexbox |
Grid |
|---|---|---|
Dimensi |
1 dimensi (baris atau kolom) |
2 dimensi (baris dan kolom sekaligus) |
Cocok untuk |
Navbar, tombol sejajar, daftar item, centering |
Layout halaman keseluruhan, dashboard, galeri foto |
Kontrol ukuran |
Item menyesuaikan konten (content-first) |
Kolom/baris didefinisikan dulu, item mengikuti (layout-first) |
Sifat |
Elemen bisa "mengalir" fleksibel |
Struktur grid lebih kaku & presisi |
Aturan praktis: Kalau kamu berpikir "saya ingin mengatur baris ATAU kolom" - Flexbox. Kalau kamu berpikir "saya ingin mengatur baris DAN kolom sekaligus, dan ingin semuanya sejajar rapi" - Grid. Faktanya, dalam proyek nyata, keduanya sering dipakai bersamaan: Grid untuk struktur besar halaman (header, sidebar, content, footer), dan Flexbox untuk menyusun elemen-elemen kecil di dalam masing-masing bagian tersebut (misalnya isi navbar).
9. Media Query & Responsive Design
Responsive design adalah pendekatan membuat 1 halaman web yang tampilannya menyesuaikan diri di berbagai ukuran layar - dari HP, tablet, hingga desktop - tanpa perlu membuat halaman terpisah untuk tiap device.
9.1 Kenapa Responsive Design Wajib?
Bayangkan tanpa responsive design: layout 3 kolom yang didesain untuk layar desktop 1200px, dibuka di HP dengan layar 375px. Kolom-kolom itu akan "diperas" jadi sangat sempit, teks jadi tidak terbaca, atau malah muncul scrollbar horizontal yang mengharuskan user menggeser layar ke samping - pengalaman yang sangat buruk. Mengingat mayoritas trafik web saat ini datang dari perangkat mobile, mengabaikan responsive design berarti mengabaikan sebagian besar calon pengguna.
9.2 Media Query
9.3 Mobile-First vs Desktop-First
|
Pendekatan |
Cara kerja |
Kelebihan |
|---|---|---|
Mobile-first (disarankan) |
Style dasar untuk mobile, lalu min-width menambah kompleksitas untuk layar besar |
CSS lebih ringan di HP (device dengan resource paling terbatas dilayani duluan), memaksa developer fokus konten prioritas |
Desktop-first |
Style dasar untuk desktop, lalu max-width menyederhanakan untuk layar kecil |
Lebih intuitif jika desain awal dibuat untuk desktop, tapi sering menghasilkan CSS override yang lebih rumit |
Kenapa mobile-first jadi standar industri saat ini? Karena lebih mudah "menambahkan" kompleksitas seiring bertambah lebarnya layar, dibanding "membongkar" layout kompleks jadi sederhana. Selain itu, browser mobile akan mengunduh & memproses CSS lebih sedikit karena style tambahan hanya dimuat saat kondisi min-width terpenuhi.
9.4 Breakpoint Umum (Acuan, Bukan Aturan Mutlak)
Catatan penting: breakpoint sebaiknya ditentukan berdasarkan di titik mana layout mulai "rusak" (konten berantakan / terlalu renggang), bukan berdasarkan ukuran device tertentu karena ukuran layar device di pasaran sangat beragam dan terus berubah.
9.5 Unit Responsif Tambahan
Selain media query, elemen berikut membantu membuat layout otomatis fleksibel tanpa banyak breakpoint:
Kenapa ini penting ditekankan? Pemula sering berpikir "responsive = banyak media query". Padahal, kombinasi Flexbox/Grid dengan unit fleksibel (fr, %, minmax(), auto-fit) bisa membuat layout responsif secara alami dengan jauh lebih sedikit kode media query.
10. Rangkuman
|
Konsep |
Fungsi Utama |
Analogi |
|---|---|---|
Selector |
Menunjuk elemen mana yang di-style |
Alamat rumah |
Cascade & Specificity |
Menentukan aturan mana yang menang saat bentrok |
Hierarki komando |
Box Model |
Struktur ruang tiap elemen |
Kotak berlapis (isi, bantalan, bingkai, jarak) |
Typography |
Keterbacaan & estetika teks |
Tata letak huruf di buku |
Positioning |
Menempatkan elemen di luar alur normal |
Menempel stiker di posisi tertentu |
Flexbox |
Layout 1 dimensi |
Barisan orang mengantre |
Grid |
Layout 2 dimensi |
Papan catur |
Media Query |
Adaptasi tampilan sesuai layar |
Baju yang menyesuaikan ukuran badan |