Ilustrasi bingkai bersarang menunjukkan lapisan box model CSS

Pernah menulis width: 300px lalu heran kenapa kotaknya terlihat lebih lebar dari 300px? Atau memberi jarak tapi background-nya ikut melebar ke tempat yang tidak diinginkan? Selamat, kamu bertemu dengan konsep paling fundamental sekaligus paling sering disalahpahami di CSS: box model. Ini episode ketiga dari seri CSS Basic, dan memahaminya akan menjelaskan setengah dari semua "keanehan" CSS yang pernah kamu alami.

Dua persepsi salah yang perlu diluruskan. Pertama, banyak pemula mengira width adalah lebar total elemen yang terlihat. Bukan. Secara default, width hanya mengatur lebar isi kotak, sementara padding dan border menempel di luarnya dan membuat totalnya membengkak. Kedua, banyak yang menganggap margin dan padding itu "sama-sama jarak" sehingga pakai yang mana saja terserah. Padahal keduanya hidup di sisi berlawanan dari border, dan salah pilih menimbulkan bug yang membingungkan, terutama soal background.

Setiap Elemen Adalah Kotak Berlapis

Di CSS, semuanya adalah kotak persegi, dari h1 sampai span. Setiap kotak tersusun dari empat lapis, dari dalam ke luar:

  1. Content: isi kotaknya, teks atau gambar. Ukurannya diatur width dan height.
  2. Padding: jarak di dalam kotak, antara isi dan border. Ikut kena background.
  3. Border: garis tepi kotak. Batas antara dalam dan luar.
  4. Margin: jarak di luar kotak, mendorong elemen tetangga menjauh. Selalu transparan, tidak pernah kena background.

Analogi yang paling nempel: foto berbingkai di dinding. Fotonya adalah content. Kardus alas di antara foto dan bingkai adalah padding. Bingkai kayunya adalah border. Jarak yang kamu sisakan antara bingkai ini dan bingkai sebelahnya adalah margin. Atau analogi paket pos: barangnya content, bubble wrap-nya padding, kardusnya border, ruang kosong antar paket di rak adalah margin.

.kartu {
  width: 300px;
  padding: 20px;
  border: 5px solid #23262e;
  margin: 30px;
}

Dengan box model default, lebar total kotak di atas BUKAN 300px. Hitungannya: 300 (content) + 40 (padding kiri-kanan) + 10 (border kiri-kanan) = 350px. Margin 30px tidak masuk hitungan lebar kotak, dia hanya mendorong tetangganya menjauh. Inilah jebakan klasiknya: kamu menulis 300px, browser merender 350px.

Berhenti dan tebak dulu! Berapa lebar total kotak ini di layar?

.kotak {
  width: 200px;
  padding: 10px;
  border: 2px solid black;
}
Jawaban: 224px. 200 (content) + 20 (padding kiri 10 + kanan 10) + 4 (border kiri 2 + kanan 2) = 224px. Kalau kamu menebak 200px, kamu tidak sendirian, hampir semua pemula menebak begitu. Cara berpikir "width = lebar total" memang lebih masuk akal bagi manusia, dan untungnya CSS menyediakan cara untuk mewujudkannya, lanjut baca.

Box-sizing, Obatnya Rasa Heran

Properti box-sizing mengubah arti width dan height. Nilai default-nya content-box: width hanya untuk isi, seperti contoh di atas. Nilai border-box: width mencakup isi + padding + border. Dengan border-box, kotak width: 200px tetap 200px total walau kamu menambah padding dan border, isi di dalamnya yang mengecil menyesuaikan.

.kotak {
  box-sizing: border-box;
  width: 200px;      /* total tetap 200px, titik. */
  padding: 10px;
  border: 2px solid black;
}

Karena border-box jauh lebih intuitif, hampir semua developer profesional menerapkannya ke seluruh halaman di awal stylesheet:

* {
  box-sizing: border-box;
}

Bintang * adalah universal selector, membidik semua elemen. Satu baris ini menghemat ratusan perhitungan manual sepanjang proyek. Mulai sekarang, jadikan ini baris pertama di setiap file CSS-mu.

Margin vs Padding, Kapan Pakai yang Mana

Aturan praktisnya sederhana. Mau memberi napas di dalam kotak supaya isi tidak mepet tepi, dan background ikut meluas? Pakai padding. Contoh: tombol butuh ruang di dalam supaya teksnya tidak menempel garis tepi. Mau memberi jarak antar kotak? Pakai margin. Contoh: jarak antara dua kartu artikel.

Uji cepatnya: kalau kamu memberi background berwarna ke elemen itu, area mana yang ikut berwarna? Padding ikut berwarna, margin tidak. Jadi kalau "background berhenti di tempat yang aneh", hampir pasti kamu memakai margin di tempat yang seharusnya padding, atau sebaliknya.

Dua trik margin yang wajib tahu. Pertama, margin: 0 auto; menengahkan kotak secara horizontal (margin kiri-kanan otomatis sama besar), pola klasik untuk membatasi lebar konten. Kedua, shorthand: margin: 10px 20px; artinya atas-bawah 10px, kiri-kanan 20px. margin: 10px 20px 30px; artinya atas 10, kiri-kanan 20, bawah 30. Urutannya selalu searah jarum jam mulai dari atas: atas, kanan, bawah, kiri. Berlaku sama untuk padding dan border-width.

Berhenti dan tebak dulu! Kamu punya tombol dengan background oranye. Teksnya mepet ke tepi tombol. Properti apa yang ditambah, dan kenapa bukan yang satunya?

.tombol {
  background: #E8590C;
  color: white;
  /* teks mepet tepi, tambah apa? */
}
Jawaban: padding, misalnya padding: 10px 20px;. Karena ruang yang dibutuhkan ada di dalam tombol, antara teks dan tepi, dan area itu harus ikut berwarna oranye. Kalau kamu memakai margin, tombolnya tidak membesar sama sekali, yang ada tombolnya malah menjauhi tetangganya sementara teks tetap mepet. Ingat: padding = napas di dalam (ikut background), margin = jarak ke tetangga (transparan).

Kuis cepat: Dengan box-sizing: border-box, width: 300px; padding: 20px;, berapa lebar total kotaknya?

Margin Collapsing, Keanehan yang Perlu Dikenal

Ada satu perilaku margin yang mengejutkan hampir semua pemula: margin collapsing. Ketika dua margin vertikal bertemu, keduanya tidak dijumlahkan, melainkan yang terbesar yang menang. Dua kotak bertumpuk yang masing-masing punya margin-bottom: 20px dan margin-top: 20px tidak berjarak 40px, melainkan 20px.

Kenapa begitu? Ini keputusan desain dari era awal web untuk teks dokumen: jarak antar paragraf sebaiknya konsisten, bukan berlipat ganda. Setelah tahu aturannya, kamu tidak akan panik lagi saat jarak vertikal "tidak sesuai hitungan". Kalau kamu memang butuh jarak yang dijumlahkan, pakai padding pada wadahnya atau gap pada flex/grid sebagai gantinya. Dan kalau masih bingung margin mana yang menang dalam kasus rumit, buka DevTools, arahkan ke elemennya, dan lihat diagram box model: angka margin yang aktif terlihat jelas di sana.

Berhenti dan tebak dulu! Dua paragraf bertumpuk. Berapa jarak vertikal di antara keduanya?

p.atas { margin-bottom: 30px; }
p.bawah { margin-top: 20px; }
Jawaban: 30px, bukan 50px. Margin vertikal yang bersentuhan mengalami collapsing: hanya nilai terbesar yang berlaku. Ini bukan bug, ini spesifikasi. Margin horizontal tidak mengalami collapsing, hanya vertikal. Setelah paham, kamu akan berhenti "menambal" dengan margin raksasa dan mulai mengatur jarak dengan sadar.

Latihan: Bedah Kotak dengan DevTools

Latihan kali ini memakai senjata rahasia developer: Chrome DevTools.

  1. Tambahkan * { box-sizing: border-box; } di baris pertama style.css halaman profilmu.
  2. Buka halamanmu di Chrome, klik kanan salah satu kartu, pilih Inspect. Di panel Styles, arahkan ke diagram box model (kotak berlapis warna-warni di bawah). Arahkan mouse ke tiap lapis: content, padding, border, margin, dan perhatikan area yang disorot di halaman.
  3. Ubah langsung nilai padding dan margin dari DevTools (klik angkanya, ketik angka baru). Perhatikan perbedaannya secara visual. Ini cara tercepat memahami beda padding vs margin, jauh lebih cepat daripada menebak dari teori.
  4. Buat dua kartu berdampingan: beri masing-masing width: 45% dan padding 20px. Tanpa border-box, totalnya akan melebihi 100 persen dan kartu kedua jatuh ke bawah. Dengan border-box, keduanya muat. Coba matikan-nyalakan aturan box-sizing-nya dan lihat bedanya. Jangan cuma baca, buktikan sendiri.

Di episode berikutnya, Mengatur Tata Letak Web dengan Display dan Position, kita naik level: dari mengukur kotak ke mengatur posisi kotak. Kamu akan paham kenapa elemen ada yang sebaris dan ada yang turun baris, plus cara menempelkan elemen di tempat yang kamu mau, seperti badge notifikasi di pojok kartu atau menu yang tetap di atas saat di-scroll.