Penggabungan margin

Kondisi margin yang menyatu antar elemen dan teknik mengendalikannya.

Daftar isi

Margin vertikal pada dua kotak yang bertetangga kadang tidak berjumlah, melainkan menyatu menjadi satu nilai. Peristiwa ini disebut margin collapse, yaitu penyatuan margin vertikal antar kotak pada alur normal. Topik ini merinci kondisi yang memicu penggabungan, kondisi yang mencegahnya, serta teknik menyusun jarak agar hasilnya dapat diprediksi.

Kondisi margin yang menyatu#

Penggabungan terjadi dalam tiga kondisi pada alur normal. Kondisi pertama adalah dua saudara searah, yaitu dua kotak yang mengalir ke bawah secara berurutan: margin-bottom kotak atas dan margin-top kotak bawah menyatu menjadi satu margin. Kondisi kedua adalah induk dengan anak pertama atau terakhir. Apabila tidak ada padding, border, ataupun content teks di antara tepi induk dan anaknya, margin anak keluar dan menyatu dengan margin induk. Kondisi ketiga adalah kotak kosong yang tidak memiliki content, padding, border, maupun tinggi, sehingga margin atas dan bawah kotak itu sendiri menyatu.

Nilai yang diambil adalah margin yang lebih besar. Pertemuan margin-bottom: 40px dengan margin-top: 20px menghasilkan jarak 40 piksel, bukan 60 piksel. Apabila salah satu marginnya negatif, margin positif terbesar dijumlahkan dengan margin negatif yang mutlaknya paling besar. Hasilnya selalu satu nilai, dan tidak ada sisa margin yang tertinggal di antara kedua kotak.

Kondisi yang tidak menyatu#

Konteks formatting yang baru menghentikan penggabungan. Item di dalam kontainer flex dan grid tidak pernah saling menggabungkan margin, sehingga margin-bottom: 40px dan margin-top: 20px benar-benar berjumlah 60 piksel. Elemen yang membentuk block formatting context baru, misalnya karena overflow selain visible, juga memisahkan marginnya dari kotak di sekitarnya. Elemen yang di-float atau diposisikan absolute pun berada di luar perhitungan penggabungan.

Pemisah fisik pada induk bekerja dengan cara serupa. Padding atau border meski setipis satu piksel menghentikan keluarnya margin anak pertama atau terakhir. Content teks di antara tepi induk dan anaknya juga menghalangi. Kondisi-kondisi ini dapat dimanfaatkan secara disengaja, tetapi mengandalkan efek samping seperti padding satu piksel demi menahan margin membuat layout rapuh dan sulit dijelaskan kepada rekan tim.

Alasan teknisnya dapat dirunut ke konteks formatting. Kontainer flex dan grid membentuk konteks formattingnya sendiri, dan margin setiap item diperlakukan sebagai bagian dari item itu, bukan bagian dari alur dokumen di sekitarnya. Elemen dengan overflow selain visible membentuk block formatting context baru, sehingga margin anak pertama dan terakhirnya tidak lagi keluar menuju kotak di sekitarnya. Dengan memahami asalnya, pencegahan penggabungan menjadi keputusan yang disengaja, bukan coba-coba.

Mengendalikan jarak dengan aman#

Dua kebiasaan menjaga agar jarak tetap dapat diprediksi. Kebiasaan pertama adalah memilih satu arah margin, misalnya hanya margin-bottom, sehingga dua margin tidak pernah bertemu dan tidak ada penggabungan antar saudara. Kebiasaan kedua adalah memakai gap pada kontainer flex dan grid untuk jarak antar item, karena gap bukan margin dan tidak terlibat penggabungan apa pun. Untuk induk, display: flow-root menghentikan keluarnya margin anak tanpa perlu menambah padding atau border.

css Contoh: satu arah margin dan gap
.seksi {
  margin-bottom: 24px;   /* hanya satu arah, tidak ada dua margin yang bertemu */
}

.daftar-piket {
  display: flex;
  flex-direction: column;
  gap: 12px;             /* jarak antar item, bukan margin */
}

Demo berikut membandingkan dua kotak dengan nilai margin yang sama pada dua konteks. Pada alur normal, margin-bottom: 40px dan margin-top: 20px menyatu menjadi jarak 40 piksel. Pada konteks flex, keduanya berjumlah 60 piksel. Perhatikan lebar garis kuning di antara kedua kotak pada setiap konteks, lalu hubungkan selisihnya dengan konteks formattingnya.

Pemilihan arah margin sebaiknya ditetapkan sekali dan dipatuhi di seluruh proyek. Konvensi yang umum adalah margin-bottom karena alur membaca bergerak ke bawah, dan elemen pertama dalam sebuah deret tidak membawa margin atas yang ikut dihitung. Konvensi tunggal ini juga memudahkan pencarian sumber jarak pada panel inspeksi, karena seluruh jarak vertikal berasal dari satu properti yang sama.

Kode sumber demo
<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="UTF-8">
  <title>Penggabungan margin</title>
  <link rel="stylesheet" href="index.css">
</head>
<body>
  <h1>Dua kotak: margin-bottom 40px dan margin-top 20px</h1>

  <p class="label">Alur normal: menyatu menjadi 40px</p>
  <div class="kontainer">
    <div class="kotak margin-atas">kotak atas</div>
    <div class="kotak margin-bawah">kotak bawah</div>
  </div>

  <p class="label">Konteks flex: berjumlah 60px</p>
  <div class="kontainer kontainer-flex">
    <div class="kotak margin-atas">kotak atas</div>
    <div class="kotak margin-bawah">kotak bawah</div>
  </div>

<style>
/* Demo penggabungan margin: alur normal vs konteks flex */

body {
  margin: 0;
  padding: 20px;
  font-family: sans-serif;
}

h1 {
  font-size: 17px;
  margin: 0 0 12px;
}

.label {
  font-size: 14px;
  margin: 12px 0 6px;
}

.kontainer {
  background: #fde68a;  /* kuning: jarak antar kotak terlihat sebagai garis kuning */
  padding: 6px;
}

.kontainer-flex {
  display: flex;
  flex-direction: column;
}

.kotak {
  background: #bfdbfe;
  border: 2px solid #1d4ed8;
  padding: 8px;
}

.margin-atas {
  margin-bottom: 40px;
}

.margin-bawah {
  margin-top: 20px;
}

</style>
<style>
/* Demo penggabungan margin: alur normal vs konteks flex */

body {
  margin: 0;
  padding: 20px;
  font-family: sans-serif;
}

h1 {
  font-size: 17px;
  margin: 0 0 12px;
}

.label {
  font-size: 14px;
  margin: 12px 0 6px;
}

.kontainer {
  background: #fde68a;  /* kuning: jarak antar kotak terlihat sebagai garis kuning */
  padding: 6px;
}

.kontainer-flex {
  display: flex;
  flex-direction: column;
}

.kotak {
  background: #bfdbfe;
  border: 2px solid #1d4ed8;
  padding: 8px;
}

.margin-atas {
  margin-bottom: 40px;
}

.margin-bawah {
  margin-top: 20px;
}

</style></body>
</html>

Kesalahan umum#

Keluhan yang paling sering muncul adalah jarak antar seksi yang hilang atau berlipat tanpa sebab yang jelas. Penyebabnya hampir selalu penggabungan yang tidak diperhitungkan, misalnya margin-top pada judul yang menyatu dengan margin-bottom seksi di atasnya. Perbaikannya adalah menetapkan satu arah margin per komponen dan menghitung jarak vertikal dari satu sumber saja.

Kasus kedua adalah margin anak yang keluar dari induknya, sehingga induk tampak tidak memberi ruang sama sekali. Kondisi ini terjadi bila induk tidak memiliki padding, border, ataupun content pemisah pada sisi yang bersangkutan. Menetapkan display: flow-root pada induk, atau menambahkan padding setipis satu piksel, menghentikan keluarnya margin tersebut.

Kasus ketiga melibatkan kotak kosong, misalnya pembatas div tanpa isi. Margin atas dan bawahnya menyatu sendiri, sehingga jarak yang diharapkan sebesar jumlah keduanya hanya muncul setengahnya. Memberikan satu karakter isi, satu padding, atau satu border pada pembatas itu menyelesaikan masalahnya.

Ringkasan#

  • Margin vertikal dua saudara searah, margin induk dengan anak tepi, dan margin kotak kosong menyatu menjadi satu nilai, yaitu yang lebih besar.
  • Konteks flex dan grid, pembentukan block formatting context melalui overflow selain visible, serta padding atau border pemisah mencegah penggabungan.
  • Jarak yang aman ditata dengan satu arah margin per komponen, gap antar item flex atau grid, dan display: flow-root pada induk yang perlu menahan margin anaknya.

Referensi#