kodingup.camp

Beranda/HTML, CSS & SCSS Mastery

Review & Diskusi Styling

Modul 6 dari 114 menit bacaStyling Review & Discussion

Isi modul

    Kenapa ini penting

    Menulis CSS yang "jalan" itu mudah. Menulis CSS yang masih bisa dirawat setelah enam bulan, oleh lima orang berbeda, dengan ratusan komponen, itu tantangan sebenarnya. CSS punya satu sifat berbahaya: semua selector bersifat global. Aturan .judul yang kamu tulis untuk halaman blog bisa diam-diam merusak .judul di halaman checkout. Lama-lama tim jadi takut menghapus CSS apa pun ("jangan-jangan masih dipakai"), file membengkak, dan !important bertebaran.

    Modul ini adalah sesi code review. Kamu akan belajar konvensi penamaan BEM, cara mengorganisasi file, peran reset atau normalize, lalu mempraktikkannya dengan merapikan CSS yang berantakan. Anggap ini seperti merapikan dapur: bumbu diberi label, alat dikelompokkan, dan semua orang tahu di mana mencari sesuatu.

    Konsep inti

    Gejala CSS yang perlu di-review

    Saat me-review kode CSS (milikmu sendiri atau orang lain), cari tanda-tanda ini:

    Gejala Kenapa bermasalah
    Selector panjang seperti .page .content div ul li a Specificity tinggi, rapuh saat struktur HTML berubah
    Banyak !important Tanda perang specificity
    Styling berbasis ID Sulit ditimpa dan tidak bisa dipakai ulang
    Nilai "ajaib" berulang (#3b82f6 muncul 40 kali) Ganti warna merek berarti ubah 40 tempat
    Nama class berdasarkan tampilan (.merah, .kiri-20) Saat desain berubah, nama jadi bohong
    Satu file 5.000 baris Sulit dicari, rawan konflik saat kerja tim

    BEM: Block, Element, Modifier

    BEM adalah konvensi penamaan class yang membuat setiap komponen punya "namespace" sendiri.

    <article class="kartu kartu--unggulan">
      <img class="kartu__gambar" src="..." alt="...">
      <h3 class="kartu__judul">Kopi Aren</h3>
      <button class="tombol tombol--utama">Beli</button>
    </article>
    

    Keuntungan BEM:

    Aturan praktis: jangan membuat "cucu" seperti .kartu__badan__judul. Element selalu langsung milik block, walaupun di HTML posisinya bersarang dalam. Kalau sebuah bagian sudah cukup kompleks untuk punya anak-anak sendiri, jadikan block baru.

    BEM bukan satu-satunya cara. Ada pendekatan utility-first (seperti Tailwind CSS) dan CSS Modules di React yang otomatis membuat nama class unik. Namun memahami BEM membantumu berpikir dalam komponen, apa pun alat yang nanti kamu pakai.

    Reset vs normalize

    Setiap browser punya gaya bawaan (user agent stylesheet): margin di body, ukuran heading, bullet di list. Gaya bawaan ini sedikit berbeda antar browser.

    Proyek modern biasanya memakai reset modern yang ringkas: beberapa baris yang memperbaiki hal paling mengganggu tanpa menghapus semuanya:

    *, *::before, *::after { box-sizing: border-box; }
    * { margin: 0; }
    body { line-height: 1.5; -webkit-font-smoothing: antialiased; }
    img, picture, video, canvas, svg { display: block; max-width: 100%; }
    input, button, textarea, select { font: inherit; }
    p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }
    

    Organisasi file

    Urutan yang sehat bergerak dari yang paling umum ke yang paling spesifik (dikenal juga sebagai pola ITCSS, "segitiga terbalik"):

    1. Tokens / settings: custom properties warna, spacing, font.
    2. Reset / base: reset dan gaya elemen dasar (body, a, h1).
    3. Layout: kerangka halaman (.container, .grid, header, footer).
    4. Components: block BEM (.kartu, .tombol, .modal).
    5. Utilities: class kecil satu tugas (.sr-only, .text-center) yang memang boleh menang.

    CSS modern menyediakan @layer untuk mengunci urutan ini. Aturan di layer yang dideklarasikan belakangan selalu menang atas layer sebelumnya, berapa pun specificity-nya:

    @layer reset, base, layout, components, utilities;
    

    Contoh kode

    Studi kasus: CSS warisan dari proyek lama.

    /* SEBELUM: berantakan */
    #main .content div.box { background: #fff; border: 1px solid #ddd; padding: 20px; }
    #main .content div.box h3 { color: #3b82f6; font-size: 20px; margin: 0 0 10px 0; }
    #main .content div.box p { color: #666; }
    .blue { color: #3b82f6 !important; }
    .box.special { border: 2px solid #3b82f6; }
    #main .content div.box a { background: #3b82f6; color: white; padding: 10px 20px; display: inline-block; }
    #main .content div.box a:hover { background: #2563eb; }
    

    Masalahnya: specificity (1,2,2) dan lebih, warna #3b82f6 diulang empat kali, !important, class .blue yang namanya berdasarkan tampilan, dan .box tidak bisa dipakai di luar #main .content.

    /* SESUDAH: rapi, terorganisasi, BEM + custom properties + @layer */
    @layer reset, tokens, components, utilities;
    
    @layer reset {
      *, *::before, *::after { box-sizing: border-box; }
      * { margin: 0; }
      img { display: block; max-width: 100%; }
      button, input { font: inherit; }
    }
    
    @layer tokens {
      :root {
        --warna-utama: #3b82f6;
        --warna-utama-gelap: #2563eb;
        --warna-teks-redup: #666;
        --warna-garis: #ddd;
        --ruang-2: 0.5rem;
        --ruang-3: 0.75rem;
        --ruang-5: 1.25rem;
      }
    }
    
    @layer components {
      .kartu {
        padding: var(--ruang-5);
        background: #fff;
        border: 1px solid var(--warna-garis);
      }
      .kartu--unggulan { border: 2px solid var(--warna-utama); }
    
      .kartu__judul {
        margin-bottom: var(--ruang-2);
        font-size: 1.25rem;
        color: var(--warna-utama);
      }
      .kartu__teks { color: var(--warna-teks-redup); }
    
      .tombol {
        display: inline-block;
        padding: var(--ruang-3) var(--ruang-5);
        color: white;
        background: var(--warna-utama);
        text-decoration: none;
        transition: background-color 150ms ease;
      }
      .tombol:hover { background: var(--warna-utama-gelap); }
    }
    
    @layer utilities {
      /* Utility menang karena layer-nya paling akhir, tanpa perlu !important */
      .teks-utama { color: var(--warna-utama); }
    }
    /* → Semua selector komponen bernilai (0,1,0) atau (0,1,1) untuk :hover.
         Ganti warna merek cukup di satu baris: --warna-utama. */
    
    <article class="kartu kartu--unggulan">
      <h3 class="kartu__judul">Paket Hemat</h3>
      <p class="kartu__teks">Dua gelas kopi susu aren.</p>
      <a class="tombol" href="/pesan">Pesan</a>
    </article>
    

    Struktur folder yang bisa kamu pakai untuk proyek CSS murni:

    css/
    ├── main.css          # hanya berisi @layer dan @import ke file lain
    ├── tokens.css
    ├── reset.css
    ├── layout.css
    └── components/
        ├── kartu.css
        └── tombol.css
    

    Catatan: @import di CSS murni membuat browser mengunduh file secara berantai, jadi untuk produksi biasanya file digabung oleh build tool seperti Vite, atau kamu memakai Sass yang menggabungkan semuanya menjadi satu file saat compile.

    Kesalahan umum

    1. Menamai class berdasarkan tampilan (.merah, .besar). Cara benar: namai berdasarkan peran (.tombol--bahaya, .judul-halaman).
    2. BEM bertingkat seperti .kartu__badan__judul. Cara benar: .kartu__judul, atau pecah jadi block baru.
    3. Menulis selector BEM bersarang seperti .kartu .kartu__judul. Ini menaikkan specificity tanpa manfaat. Cara benar: cukup .kartu__judul.
    4. Memasang reset agresif lalu lupa gaya fokus dan list. Cara benar: pakai reset ringkas dan tambahkan kembali gaya penting seperti :focus-visible.
    5. Merapikan sambil mengubah tampilan. Refactor harus menghasilkan tampilan identik. Cara benar: bandingkan screenshot sebelum dan sesudah.

    Latihan

    1. Mudah, Ubah HTML ini ke penamaan BEM: <div class="profil"><img class="foto"><h2 class="nama"></h2><p class="bio"></p></div>, termasuk variasi profil "terverifikasi".
    2. Sedang, Identifikasi minimal empat masalah pada CSS berikut, lalu tulis ulang: #nav ul li a { color: red !important; } #nav ul li a.active { color: blue !important; font-weight: bold; } .kiri { float: left; }.
    3. Menantang, Susun file main.css yang mendeklarasikan urutan layer reset, tokens, layout, components, utilities, lalu buktikan bahwa class .sembunyi { display: none; } di layer utilities menang atas #app .kartu { display: block; } di layer components.
    Lihat solusi
    <!-- Soal 1 -->
    <div class="profil profil--terverifikasi">
      <img class="profil__foto" src="foto.jpg" alt="Foto Rina">
      <h2 class="profil__nama">Rina</h2>
      <p class="profil__bio">Frontend developer.</p>
    </div>
    
    /* Soal 2
       Masalah: (1) styling lewat ID, (2) selector terlalu panjang dan bergantung struktur,
       (3) !important dipakai untuk saling timpa, (4) nama .kiri berdasarkan tampilan,
       (5) float untuk layout sudah kuno, sebaiknya Flexbox. */
    .nav__link { color: red; }
    .nav__link--aktif { color: blue; font-weight: bold; }
    .nav__list { display: flex; gap: 1rem; }
    
    /* Soal 3 */
    @layer reset, tokens, layout, components, utilities;
    
    @layer components {
      #app .kartu { display: block; }    /* specificity (1,1,0) */
    }
    @layer utilities {
      .sembunyi { display: none; }        /* specificity (0,1,0) */
    }
    /* → <div id="app"><div class="kartu sembunyi">...</div></div> TIDAK tampil.
         Antar layer, urutan layer menang duluan sebelum specificity dibandingkan. */
    

    Ringkasan

    Kuis pemahaman

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