HTML5 dan CSS3

Belum masuk. Progresmu tidak tersimpan.

Masuk
  • Bab 6 dari 10
  • 30 menit
  • 1 latihan kode
  • 4 soal kuis

Box Model, Display, dan Position

Di bab ini (9 bagian)
  1. Tujuan
  2. Semua elemen adalah kotak
  3. Hitung lebarnya: content-box vs border-box
  4. Margin collapse singkat
  5. display: bagaimana elemen mengalir
  6. position: memindahkan elemen
  7. z-index: siapa di atas
  8. Kesalahan umum
  9. Rangkuman

Tujuan bab ini

  • Memahami empat lapisan box model dan menghitung ukuran total sebuah elemen.
  • Memakai box-sizing: border-box dan mengenali margin collapse.
  • Membedakan display block, inline, inline-block, dan none.
  • Mengatur posisi elemen dengan position dan menumpuknya dengan z-index.

Semua elemen adalah kotak

Buka DevTools di browser mana pun, arahkan kursor ke sebuah elemen, dan kamu akan melihat kotak berwarna-warni. Itu box model: setiap elemen HTML digambar sebagai kotak dengan empat lapisan, dari dalam ke luar.

LapisanIsinyaProperti
contentteks, gambar, anak elemenwidth, height
paddingruang antara content dan border, ikut warna backgroundpadding
bordergaris pembatasborder
marginjarak ke elemen lain, selalu transparanmargin

Analoginya seperti kado: content adalah barangnya, padding adalah bubble wrap, border adalah kardus, dan margin adalah jarak antar kardus di rak.

Box model dan box-sizing

.kartu {
  width: 300px;
  padding: 20px;
  border: 2px solid #1572b6;
  margin: 16px;
}

Shorthand padding dan margin mengikuti arah jarum jam: padding: 10px 20px 30px 40px berarti atas, kanan, bawah, kiri. Dua nilai (10px 20px) berarti atas-bawah lalu kiri-kanan.

Hitung lebarnya: content-box vs border-box

Secara default browser memakai box-sizing: content-box. Artinya width hanya untuk area content, lalu padding dan border ditambahkan di luarnya. Lebar .kartu di atas yang terlihat di layar:

300 (content) + 20 + 20 (padding) + 2 + 2 (border) = 344px

Margin tidak dihitung dalam lebar kotak, tetapi tetap memakan ruang di sekitarnya. Inilah sumber banyak kebingungan: kamu menulis 300px, tapi kotaknya 344px dan tiba-tiba layout meluber.

Solusinya border-box: width sudah termasuk padding dan border, sehingga content yang menyusut.

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

Dengan aturan ini, .kartu di atas tepat 300px lebarnya, dan area content-nya 300 - 40 - 4 = 256px. Hampir semua proyek modern menaruh tiga baris ini di paling atas file CSS.

Margin collapse singkat

Ada satu perilaku aneh yang perlu kamu tahu: margin vertikal dua elemen block yang bertetangga bisa menyatu. Kalau paragraf pertama punya margin-bottom: 20px dan paragraf kedua punya margin-top: 30px, jaraknya bukan 50px, melainkan 30px (diambil yang terbesar).

Margin collapse hanya terjadi pada margin atas-bawah di alur normal. Margin kiri-kanan tidak pernah menyatu, dan item di dalam flex atau grid container juga tidak mengalaminya. Kalau jarak terasa "hilang", kemungkinan besar ini penyebabnya.

display: bagaimana elemen mengalir

Properti display menentukan cara elemen ikut dalam alur halaman.

NilaiPerilakuContoh bawaan
blockmulai di baris baru, melebar penuh, width/height berlakudiv, p, h1, section
inlinemengalir dalam teks, width/height diabaikanspan, a, strong
inline-blockmengalir seperti inline, tapi ukuran bisa diaturbutton, input
nonedihapus dari layout, tidak memakan ruangdipakai untuk menyembunyikan
<p>Harga <span class="label">PROMO</span> hari ini</p>
.label {
  display: inline-block;
  padding: 4px 8px;
  width: 80px;
  background: #c5e1a5;
}

Dengan inline-block, label tetap berada di tengah kalimat tetapi lebarnya benar-benar 80px. Kalau diganti inline, width diabaikan dan padding atas-bawahnya tidak mendorong baris lain. Kalau diganti block, label pindah ke baris sendiri dan memecah kalimat.

Bedakan display: none dengan visibility: hidden. Yang pertama menghapus ruang elemen, yang kedua hanya membuatnya tak terlihat tetapi ruangnya tetap ada, jadi akan ada lubang kosong.

display: flex dan display: grid juga nilai display. Keduanya membuat elemen tetap berperilaku seperti block bagi tetangganya, sekaligus menjadi container untuk anak-anaknya. Itu bab berikutnya.

position: memindahkan elemen

NilaiMasih di alur normal?Patokan top/left
staticya (default)tidak berpengaruh
relativeya, ruang aslinya tetap dipesanposisi aslinya sendiri
absolutetidakancestor terdekat yang positioned
fixedtidakviewport, diam saat scroll
stickyya, sampai ambang tercapaimenempel saat scroll melewati ambang

"Positioned" berarti punya position selain static. Pola paling umum adalah relative pada induk, absolute pada anak:

<div class="foto">
  <img src="sepatu.jpg" alt="Sepatu">
  <span class="badge">-30%</span>
</div>
.foto {
  position: relative;
}
.badge {
  position: absolute;
  top: 8px;
  right: 8px;
}

Badge diskon akan menempel di pojok kanan atas foto. Tanpa position: relative pada .foto, badge mencari ancestor positioned berikutnya, dan kalau tidak ada, ia menempel ke pojok halaman.

Dua lainnya:

.navbar { position: fixed; top: 0; left: 0; right: 0; }
.judul-tabel { position: sticky; top: 0; }

Navbar fixed selalu di atas layar walau halaman di-scroll, jadi beri konten di bawahnya padding-top agar tidak tertutup. sticky berperilaku normal sampai jaraknya ke atas layar mencapai top: 0, lalu menempel. sticky wajib punya minimal satu nilai top/bottom/left/right, dan berhenti menempel saat induknya habis di-scroll.

z-index: siapa di atas

Saat elemen saling tumpuk, z-index menentukan urutannya. Nilai lebih besar tampil di depan.

.modal { position: fixed; z-index: 100; }
.overlay { position: fixed; z-index: 50; }

Aturan pentingnya: z-index hanya bekerja pada elemen positioned (atau item flex/grid). Selain itu, elemen positioned dengan z-index selain auto membentuk stacking context baru. Anak di dalamnya hanya bisa bertarung dengan saudara di konteks yang sama, jadi z-index: 9999 pada anak tidak bisa menembus induk yang ber-z-index: 1 di bawah elemen lain ber-z-index: 2.

Kesalahan umum

  • Lupa padding dan border menambah lebar pada content-box, lalu kolom tidak muat.
  • Memberi width pada span lalu heran tidak berubah. Ubah ke inline-block atau block.
  • Memakai absolute tanpa induk relative, sehingga elemen terbang ke pojok halaman.
  • Menulis z-index pada elemen static dan berharap ia naik ke depan.
  • Memakai display: none padahal ingin ruangnya tetap ada.

Rangkuman

  • Box model: content, padding, border, margin, dari dalam ke luar.
  • box-sizing: border-box membuat width sudah termasuk padding dan border.
  • Margin vertikal antar block bisa menyatu, diambil yang terbesar.
  • display mengatur alur: block, inline, inline-block, none.
  • position relative, absolute, fixed, dan sticky memindahkan elemen dengan patokan berbeda.
  • z-index mengatur tumpukan elemen positioned di dalam stacking context-nya.

Selesaikan bab ini

  1. 1. Baca materi
  2. 2. Latihan kode (1)
  3. 3. Kuis (4 soal)

Latihan kode: Kartu produk dengan badge diskon

HTML-nya sudah jadi, jangan diubah. Lengkapi CSS-nya:

  • Pasang box-sizing: border-box untuk semua elemen dengan selector *.
  • .kartu lebarnya 240px dengan padding: 16px dan border: 2px solid #111. Lebar yang terlihat harus tepat 240px.
  • Badge .badge menempel di pojok kanan atas kartu: position: absolute, top: 8px, right: 8px, z-index: 2. Jangan lupa kartu harus jadi patokannya.
  • .harga tetap sebaris tapi lebarnya bisa diatur: display: inline-block dan width: 120px.

Cek pemahaman

  1. 1Dengan box-sizing bawaan (content-box), berapa lebar kotak yang terlihat, tanpa menghitung margin?

    .kotak {
      width: 200px;
      padding: 10px;
      border: 5px solid black;
      margin: 20px;
    }
  2. 2Elemen dengan `position: absolute` diposisikan terhadap apa?

  3. 3Dengan `box-sizing: border-box`, nilai `width` sudah termasuk padding dan border.

  4. 4Berapa jarak vertikal antara kedua paragraf?

    <style>
      .a { margin-bottom: 20px; }
      .b { margin-top: 30px; }
    </style>
    <p class="a">Satu</p>
    <p class="b">Dua</p>