kodingup.camp

Beranda/HTML, CSS & SCSS Mastery

Fondasi Styling CSS

Modul 3 dari 116 menit bacaStyling Foundations

Isi modul

    Kenapa ini penting

    Kalau HTML adalah kerangka rumah, CSS (Cascading Style Sheets) adalah cat, lantai, perabot, dan tata ruangnya. Banyak pemula merasa CSS "tidak bisa ditebak": kenapa warnanya tidak berubah, kenapa kotaknya melebar, kenapa margin tiba-tiba hilang. Hampir semua kebingungan itu berasal dari empat konsep yang akan kamu pelajari di sini: selector, specificity, cascade, dan box model. Begitu empat hal ini kamu pahami, CSS berubah dari tebak-tebakan menjadi logika yang bisa diprediksi.

    Konsep inti

    Tiga cara memasang CSS

    Cara Contoh Kapan dipakai
    Inline <p style="color: red"> Hampir tidak pernah; sulit dirawat dan specificity-nya tinggi
    Internal <style> di dalam <head> Halaman tunggal, demo, eksperimen cepat
    Eksternal <link rel="stylesheet" href="style.css"> Standar untuk proyek nyata; satu file dipakai banyak halaman dan bisa di-cache browser

    Satu aturan CSS (rule) terdiri dari selector dan deklarasi:

    /* selector { properti: nilai; } */
    h1 {
      color: #1f2937;
      font-size: 2rem;
    }
    

    Selector

    Pseudo-class seperti :hover dan selector modern seperti :is(), :where(), :not(), dan :has() akan dibahas lebih dalam di modul berikutnya.

    Specificity: siapa yang menang

    Ketika dua aturan menargetkan elemen yang sama dengan properti yang sama, browser menghitung specificity (tingkat kekhususan). Cara mudah: anggap sebagai skor tiga angka (ID, class, tipe).

    Selector Skor (ID, class, tipe)
    p (0, 0, 1)
    .harga (0, 1, 0)
    p.harga (0, 1, 1)
    .kartu .harga (0, 2, 0)
    #produk .harga (1, 1, 0)
    inline style="" mengalahkan semua selector

    Angka dibandingkan dari kiri: satu ID mengalahkan seratus class. Pseudo-class (:hover) dan atribut ([type]) dihitung seperti class. Pseudo-element (::before) dihitung seperti tipe. :where() selalu bernilai nol, sangat berguna untuk gaya dasar yang mudah ditimpa.

    !important memaksa deklarasi menang di atas aturan biasa. Ini seperti membunyikan klakson terus-menerus: sekali dipakai, orang lain harus ikut membunyikan klakson lebih keras. Simpan untuk kasus darurat atau utility yang memang harus menang.

    Cascade

    "Cascading" berarti air terjun: aturan mengalir dan saling timpa. Urutan penentuannya, secara sederhana:

    1. Asal dan kepentingan: gaya bawaan browser, lalu gaya kamu, lalu gaya kamu yang !important.
    2. Cascade layer (@layer), kalau dipakai.
    3. Specificity.
    4. Urutan kemunculan: kalau specificity sama, aturan yang ditulis paling akhir menang.

    Inheritance (pewarisan)

    Beberapa properti otomatis diwariskan dari induk ke anak, terutama properti teks: color, font-family, font-size, line-height, text-align. Itu sebabnya cukup menulis font-family di body. Properti kotak seperti margin, padding, border, width, dan background tidak diwariskan. Kamu bisa memaksa pewarisan dengan nilai inherit, mengembalikan ke nilai awal dengan initial, atau memakai unset.

    Box model

    Setiap elemen adalah kotak berlapis, seperti paket kiriman:

    Secara default (box-sizing: content-box), width: 300px hanya untuk content. Tambah padding: 20px dan border: 2px, lebar total jadi 344px. Ini sumber bug klasik. Solusinya, hampir semua proyek modern memasang:

    *, *::before, *::after { box-sizing: border-box; }
    

    Dengan border-box, width: 300px sudah termasuk padding dan border.

    Dua hal lain tentang box model: elemen block (div, p, h1) mengambil satu baris penuh, sedangkan elemen inline (span, a, strong) mengalir di dalam teks dan mengabaikan width/height serta margin atas-bawah. Lalu ada margin collapse: margin vertikal dua blok yang berurutan tidak dijumlahkan, melainkan diambil yang terbesar.

    Unit

    Unit Relatif terhadap Cocok untuk
    px Piksel CSS (tetap) Border tipis, bayangan, detail kecil
    rem Font-size elemen <html> (default browser 16px) Ukuran font, spacing, sebagian besar ukuran
    em Font-size elemen itu sendiri Padding tombol yang ikut membesar dengan teksnya
    % Ukuran induk Lebar kolom fleksibel
    vw / vh 1% lebar / tinggi viewport Hero layar penuh, tipografi fluid
    dvh Tinggi viewport dinamis (memperhitungkan address bar HP) Section setinggi layar di mobile
    ch Lebar karakter "0" Membatasi panjang baris teks, misal max-width: 65ch

    Kenapa rem lebih disarankan daripada px untuk font? Kalau pengguna memperbesar ukuran huruf default di pengaturan browser (umum bagi pengguna dengan penglihatan terbatas), ukuran dalam rem ikut membesar, sedangkan px tidak.

    Contoh kode

    index.html:

    <!DOCTYPE html>
    <html lang="id">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>Latihan Specificity</title>
      <link rel="stylesheet" href="style.css">
    </head>
    <body>
      <div class="kartu" id="promo">
        <h2>Paket Hemat</h2>
        <p class="harga">Rp50.000</p>
        <p>Berlaku sampai akhir bulan.</p>
      </div>
    </body>
    </html>
    

    style.css:

    /* Reset box model: width sudah termasuk padding dan border */
    *, *::before, *::after { box-sizing: border-box; }
    
    body {
      font-family: system-ui, sans-serif; /* diwariskan ke semua anak */
      color: #1f2937;
      line-height: 1.6;
    }
    
    .kartu {
      width: 320px;
      padding: 1.5rem;            /* 24px kalau font root 16px */
      border: 2px solid #e5e7eb;
      margin: 2rem auto;          /* auto kiri-kanan = rata tengah */
    }
    /* → Lebar total tetap 320px berkat border-box (tanpa itu: 320 + 48 + 4 = 372px) */
    
    p { color: gray; }                 /* (0,0,1) */
    .harga { color: green; }           /* (0,1,0) menang atas p */
    .kartu .harga { color: orange; }   /* (0,2,0) menang atas .harga */
    #promo .harga { color: crimson; }  /* (1,1,0) menang atas semuanya */
    /* → Teks "Rp50.000" berwarna crimson */
    
    .kartu p { color: gray; }
    p { color: blue; }  /* ditulis belakangan, tapi specificity lebih rendah */
    /* → "Berlaku sampai..." tetap gray, karena (0,1,1) > (0,0,1); urutan hanya menentukan kalau skornya sama */
    
    h2 {
      font-size: 1.5rem;
      margin-bottom: 0.5em; /* 0.5 × font-size h2 = 12px */
    }
    

    Tips: klik kanan elemen, pilih Inspect. Di panel Styles, aturan yang kalah akan dicoret. Panel Computed menunjukkan nilai akhir dan diagram box model.

    Kesalahan umum

    1. Memakai ID untuk styling, lalu kesulitan menimpanya. Cara benar: styling dengan class, ID untuk anchor link dan JavaScript.
    2. Menambal dengan !important setiap kali gaya tidak berubah. Cara benar: cek di DevTools aturan mana yang menang, lalu perbaiki specificity atau urutan.
    3. Lupa box-sizing: border-box, sehingga elemen dengan padding meluber dari kontainernya. Cara benar: pasang reset di awal file.
    4. Bingung em bertumpuk: font-size: 1.2em di dalam induk yang juga 1.2em menghasilkan 1.44 kali. Cara benar: pakai rem untuk font-size, em hanya untuk spacing yang memang harus mengikuti teks.
    5. Memberi width atau margin atas ke elemen inline lalu heran tidak berubah. Cara benar: ubah ke display: inline-block atau block.

    Latihan

    1. Mudah, Hitung specificity: nav ul li a, .menu a:hover, #app .menu > a.
    2. Sedang, Buat kotak .kotak dengan lebar 400px, padding 2rem, border 4px. Tanpa border-box, berapa lebar totalnya? Lalu buat versi yang lebar totalnya tepat 400px.
    3. Menantang, Kamu punya .tombol { background: blue; } di file framework dan tidak boleh mengubah file itu. Elemen kamu <a class="tombol tombol-bahaya">. Tulis CSS agar tombol berwarna merah tanpa !important dan tanpa ID, lalu jelaskan kenapa berhasil.
    Lihat solusi
    /* Soal 1
       nav ul li a        → (0,0,4)
       .menu a:hover      → (0,2,1)  karena :hover dihitung seperti class
       #app .menu > a     → (1,1,1)  kombinator > tidak menambah skor
    */
    
    /* Soal 2
       Tanpa border-box: 400 + (32 × 2) + (4 × 2) = 472px
    */
    .kotak {
      box-sizing: border-box;
      width: 400px;
      padding: 2rem;
      border: 4px solid #333;
    }
    /* → total tepat 400px, area konten jadi 400 - 64 - 8 = 328px */
    
    /* Soal 3: dua cara */
    /* Cara A: specificity lebih tinggi (0,2,0) > (0,1,0) */
    .tombol.tombol-bahaya { background: red; }
    
    /* Cara B: specificity sama (0,1,0), tetapi file kamu dimuat SETELAH file framework,
       sehingga menang karena urutan */
    .tombol-bahaya { background: red; }
    

    Ringkasan

    Kuis pemahaman

    Pilih satu jawaban per soal. Penjelasan muncul setelah kamu menjawab.