Di halaman web, setiap elemen adalah kotak, dan setiap kotak punya empat lapis: content (isinya), padding (ruang di dalam), border (garis tepi), dan margin (ruang di luar). Bayangin foto berbingkai di dinding. Fotonya adalah content. Karton putih di sekeliling foto adalah padding. Bingkai kayunya border. Dinding kosong di antara dua bingkai adalah margin. Kalau kamu bilang "bingkainya 30 cm", orang perlu tahu: 30 cm itu fotonya saja, atau sampai ke bingkai? CSS punya pertanyaan yang sama, dan jawabannya ada di box-sizing.
🧪 Tebakan cepat: Kartu pesan Bu Sri ditulis
width: 300px; padding: 24px; border: 1px solid #e2e8f0;, tanpa aturan lain. Berapa lebar kartunya di layar? Jawabannya ada di bagian "content-box atau border-box".
Empat lapis kartu pesan
<div class="card">
<h3>Kamar Teras</h3>
<p class="total">2 malam × Rp 350.000 = Rp 700.000</p>
<button class="book">Pesan kamar, bayar di tempat</button>
</div>
<p class="callout">Gratis batal sampai 3 hari sebelum check-in.</p>
<style>
.card {
width: 300px;
padding: 24px; /* ruang antara isi dan garis tepi */
border: 1px solid #e2e8f0; /* garis tepi */
margin-bottom: 16px; /* jarak ke callout di bawahnya */
background: #fff;
}
.book { width: 100%; padding: 12px 16px; }
</style>
Dari dalam ke luar: content → padding → border → margin. Background putih kartu mewarnai content, padding, dan area di bawah border. Margin selalu transparan: yang kelihatan di sana adalah latar halaman.
content-box atau border-box
box-sizing menentukan width itu mengukur lapis yang mana.
content-box (bawaan browser) |
border-box |
|
|---|---|---|
width: 300px berarti |
lebar content saja | lebar sampai ke luar border |
| Lebar kartu di layar | 300 + 2 × 24 + 2 × 1 = 350px | 300px |
| Lebar content | 300px | 300 − 48 − 2 = 250px |
Tombol width: 100% dengan padding kiri-kanan 16px |
300 + 32 = 332px, 32px lebih lebar dari content, menembus padding dan border kartu | pas 250px |
Jadi jawaban tebakannya: 350px. Bawaan browser adalah content-box, jadi padding dan border ditambahkan di luar 300px. Kartu yang kamu kira 300px jadi 50px lebih lebar, dan tombol width: 100% di dalamnya menjulur keluar dari tepi kanan kartu. Makanya hampir semua project memulai CSS-nya dengan:
*, *::before, *::after {
box-sizing: border-box;
}
*memilih semua elemen,::beforedan::afterikut supaya elemen buatan CSS juga konsisten.- Setelah itu,
widthyang kamu tulis adalah lebar yang kamu lihat. Dua kartuwidth: 50%dengan padding tetap muat berdampingan, gak turun ke baris baru. box-sizingcuma berpengaruh kalau kamu menuliswidthatauheight. Kartu tanpawidthmemenuhi lebar wadahnya di kedua mode.
Padding atau margin?
- Padding adalah ruang di dalam kotak. Dia ikut berwarna background, dan ikut bisa diklik: tombol pesan dengan
padding: 12px 16pxtingginya sekitar 12 + 19 (satu baris teks) + 12 = 43px, dan seluruh area itu bisa ditekan. - Margin adalah ruang di luar kotak, untuk jarak antar elemen. Transparan, dan gak bisa diklik.
Aturan praktisnya: ruang antara isi dan tepinya sendiri itu padding, jarak antara dua elemen itu margin. Di kartu Bu Sri, 24px di dalam kartu adalah padding, 16px antara kartu dan callout adalah margin.
Margin collapse: jarak yang gak dijumlah
Callout aturan batal di bawah kartu diberi margin-top: 24px. Kartu punya margin-bottom: 16px. Jaraknya berapa?
| Pembungkusnya | Jarak kartu ke callout |
|---|---|
| Blok biasa | 24px, yang lebih besar dari 16 dan 24 |
display: flex atau grid |
16 + 24 = 40px |
Ini namanya margin collapse: dua margin vertikal yang bertemu antara elemen blok biasa melebur jadi satu, dan yang dipakai yang terbesar. Margin kiri-kanan gak pernah collapse, dan di dalam flex atau grid margin juga gak collapse. Kalau jaraknya terasa "kurang" dari yang kamu tulis, cek ini dulu.
Spacing system: kelipatan 4 atau 8
Jangan pilih jarak secara acak. Pakai kelipatan satu angka dasar, biasanya 8px, dengan 4px untuk jarak yang sangat kecil:
| Token | Nilai | Di kartu Bu Sri |
|---|---|---|
| xs | 4px | jarak nama kamar ke totalnya, jarak antar tombol malam |
| sm | 8px | jarak judul ke paragrafnya |
| md | 16px | margin kartu ke callout, padding kiri-kanan tombol |
| lg | 24px | padding kartu |
| xl | 32px | jarak antar bagian halaman |
Semua angka di kartu (4, 8, 12, 16, 24) adalah kelipatan 4, dan yang besar kelipatan 8. Kalau semua jarak datang dari daftar ini, halaman terlihat rapi tanpa harus diukur satu per satu.
⚠️ Jebakan yang sering ketemu
- Lupa
box-sizing: border-box.width: 100%ditambah padding membuat elemen lebih lebar dari wadahnya, dan muncul scroll ke samping di HP. - Menjumlahkan margin vertikal. 16 + 24 di blok biasa jadi 24, bukan 40.
- Pakai margin untuk memperbesar tombol. Area tekan cuma tumbuh dengan padding.
- Jarak acak. 13px, 17px, 22px. Ambil dari kelipatan 4 atau 8.
TL;DR: Setiap elemen adalah kotak berlapis content, padding (ruang di dalam, ikut background dan ikut bisa diklik), border, dan margin (ruang di luar, transparan, untuk jarak antar elemen). Bawaan browser content-box menambahkan padding dan border di luar width: 300 + 2 × 24 + 2 × 1 = 350px. Dengan *, *::before, *::after { box-sizing: border-box; }, width: 300px berarti 300px total, dan konten jadi 250px. Margin vertikal antar blok biasa collapse ke yang terbesar (16 dan 24 jadi 24), kecuali di flex dan grid (40). Pakai spacing system dengan base 8px (dan 4px untuk jarak kecil): 4, 8, 16, 24, 32.