Bagaimana cara menonaktifkan margin-collapsing?

202

Apakah ada cara untuk menonaktifkan margin-collapsing sama sekali? Satu-satunya solusi yang saya temukan (dengan nama "uncollapsing") memerlukan menggunakan perbatasan 1px atau padding 1px. Saya menemukan ini tidak dapat diterima: piksel asing mempersulit perhitungan tanpa alasan yang baik. Apakah ada cara yang lebih masuk akal untuk menonaktifkan margin-collapsing ini?

kjo
sumber
4
Gunakan tata letak Flex atau Grid, di mana margin collapsing tidak ada: stackoverflow.com/a/46496701/3597276
Michael Benjamin
Berikan nilai pada elemen, margin-bottomtetapi biarkan margin-topsebagai 0.
Dan Bray
Saya membuat paket untuk mempermudah perhitungan: npmjs.com/package/collapsed-margin
Owen M

Jawaban:

255

Ada dua jenis utama keruntuhan margin:

  • Runtuh margin antara elemen yang berdekatan
  • Runtuh margin antara elemen induk dan anak

Menggunakan bantalan atau batas akan mencegah keruntuhan hanya dalam kasus terakhir. Selain itu, nilai apa pun yang overflowberbeda dari default ( visible) yang diterapkan pada induk akan mencegah keruntuhan. Dengan demikian, keduanya overflow: autodan overflow: hiddenakan memiliki efek yang sama. Mungkin satu-satunya perbedaan saat menggunakan hiddenadalah konsekuensi yang tidak disengaja dari menyembunyikan konten jika orang tua memiliki ketinggian tetap.

Properti lain yang, setelah diterapkan pada induknya, dapat membantu memperbaiki perilaku ini adalah:

  • float: left / right
  • position: absolute
  • display: inline-block / flex

Anda dapat menguji semuanya di sini: http://jsfiddle.net/XB9wX/1/ .

Saya harus menambahkan bahwa, seperti biasa, Internet Explorer adalah pengecualian. Lebih khusus lagi, di IE 7 margin tidak runtuh ketika beberapa jenis tata letak ditentukan untuk elemen induk, seperti width.

Sumber: Artikel Sitepoint, Runtuh Marjin

hqcasanova
sumber
1
perhatikan bahwa bantalan juga dapat memengaruhi ini jika bukan nilai nol
Mladen Janjetovic
3
Catatan yang overflow: autodapat menyebabkan bilah gulir muncul di elemen induk, daripada membiarkan konten melimpah melimpah sesuai overflow: visible.
Leo
'overflow: auto' tampaknya tidak berfungsi di Chrome v44.
tkane2000
3
Terima kasih untuk tampilan: inline-block, itu menyelamatkan saya :)
alexcasalboni
3
Nilai apa pun yang flexberbeda dari standarnya juga akan menonaktifkan runtuhnya margin
Oly
60

Anda juga dapat menggunakan perbaikan mikro lama yang baik untuk ini.

#container:before, #container:after{
    content: ' ';
    display: table;
}

Lihat biola diperbarui: http://jsfiddle.net/XB9wX/97/

Blackgrid
sumber
Telah mengubah jawaban saya menjadi wiki komunitas. Silakan memperluasnya dengan jawaban Anda. Terima kasih.
hqcasanova
3
Saya tidak mengerti, ketika saya melihat contoh marginnya runtuh (hanya 10px ruang vertikal antara divs bukannya 20px)
Andy
1
Ini hanya membantu dalam menghapus keruntuhan di antara saudara kandung yang semuanya telah menerapkan clearfix ini. Saya telah garpu contoh untuk menunjukkan ini: jsfiddle.net/dpyuyg07 --- dan bahkan itu bukan keseluruhan cerita. Itu hanya menghilangkan runtuhnya margin yang berasal dari anak-anak elemen tempat Anda menerapkan perbaikan itu. Jika Anda ingin menambahkan margin pada wadah itu sendiri, margin masih akan runtuh, yang dapat dilihat dalam fork ini: jsfiddle.net/oew7qsjx
NicBright
4
Saya dapat menempatkan ini lebih tepat: metode clearfix hanya mencegah runtuhnya margin antara orang tua dan anak-anak. Itu tidak mempengaruhi keruntuhan antara saudara kandung yang berdekatan.
NicBright
Saya pikir saya sekarang mengerti kecenderungan Bootstrap untuk mengisi DOM dengan :beforedan :afterelemen. Saya sekarang telah menambahkan aturan ini ke stylesheet saya: div:before, div:after{content: ' '; display: table;}. Fantastis. Tiba-tiba hal-hal mulai berlaku seperti yang diharapkan.
Stijn de Witt
60

Salah satu trik rapi untuk menonaktifkan collapsing margin yang tidak memiliki dampak visual, sejauh yang saya tahu, adalah mengatur bantalan induk ke 0.05px:

.parentClass {
    padding: 0.05px;
}

Padding tidak lagi 0 sehingga collapsing tidak akan terjadi lagi tetapi pada saat yang sama padding cukup kecil sehingga secara visual akan dibulatkan menjadi 0.

Jika beberapa bantalan lain diinginkan, maka gunakan bantalan hanya ke "arah" di mana margin runtuh tidak diinginkan, misalnya padding-top: 0.05px;.

Contoh kerja:

.noCollapse {
  padding: 0.05px;
}

.parent {
  background-color: red;
  width: 150px;
}

.children {
  margin-top: 50px;

  background-color: lime;      
  width: 100px;
  height: 100px;
}
<h3>Border collapsing</h3>
<div class="parent">
  <div class="children">
  </div>
</div>

<h3>No border collapsing</h3>
<div class="parent noCollapse">
  <div class="children">
  </div>
</div>

Edit: mengubah nilai dari 0.1menjadi 0.05. Seperti yang disebutkan oleh Chris Morgan dalam komentar di bawah, dan dari pengujian kecil ini , tampaknya memang Firefox yang mempertimbangkan 0.1pxpadding. Padahal, 0.05pxsepertinya melakukan trik.

Nicu Surdu
sumber
2
Ini solusi favorit saya. Anda bahkan dapat memasukkan ini sebagai gaya default. Kenapa tidak? *{padding-top:0.1px}. Apakah kami yakin ini berfungsi di semua browser?
Nick Manning
Sejauh ini bekerja dengan cukup baik untuk saya, tetapi saya tidak mengklaim telah mengujinya secara menyeluruh di sebagian besar browser.
Nicu Surdu
2
Solusi yang sangat bagus, tampaknya berfungsi seperti yang diharapkan pada sebagian besar browser. Terima kasih telah membagikannya!
wiredolphin
1
Ini adalah solusi cerdik karena tidak menambahkan piksel ekstra dalam berbagai keadaan, karena menampilkan tinggi DPI dan perhitungan subpixel. (Firefox telah melakukan tata letak subpixel selama berabad-abad, saya percaya browser lain secara relatif baru-baru ini mengikuti.)
Chris Morgan
0.05pxsepertinya masih seperti pilihan tertentu, bukan nomor tipuan browser acak, saya lebih suka 0.01px.
Volker E.
22

overflow:hidden mencegah margin yang runtuh tetapi tidak bebas dari efek samping - yaitu ... menyembunyikan overflow.

Terlepas dari bentuk ini dan apa yang Anda sebutkan, Anda hanya perlu belajar hidup dengannya dan belajar untuk hari ini ketika mereka benar-benar berguna (datang setiap 3 hingga 5 tahun).

Litek
sumber
Telah mengubah jawaban saya menjadi wiki komunitas. Saya pikir saya sudah membahas efek samping yang Anda sebutkan dalam dua baris terakhir dari paragraf kedua: Mungkin satu-satunya perbedaan ketika menggunakan tersembunyi adalah konsekuensi yang tidak disengaja dari menyembunyikan konten jika orang tua memiliki ketinggian tetap . Tetapi jika Anda merasa perlu klarifikasi lebih lanjut, silakan berkontribusi. Terima kasih.
hqcasanova
7
overflow: autobaik untuk digunakan untuk mencegah overflow tersembunyi dan masih mencegah margin yang runtuh.
Gavin
@ Gavin, overflow:auto;membuat area konten saya memperoleh bilah gulir di beberapa halaman.
Reed
13

Sebenarnya, ada satu yang bekerja dengan sempurna:

display: flex; arah fleksibel: kolom;

selama Anda dapat hidup dengan hanya mendukung IE10 dan lebih tinggi

.container {
  display: flex;
  flex-direction: column;
    background: #ddd;
    width: 15em;
}

.square {
    margin: 15px;
    height: 3em;
    background: yellow;
}
<div class="container">
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
</div>
<div class="container">
    <div class="square"></div>
    <div class="square"></div>
    <div class="square"></div>
</div>

Daniel Koster
sumber
Agar ini berfungsi sebagai solusi umum, kita harus menambahkan ekstra <div>di dalam .container, jika tidak, .containerakan mengendalikan model kotak anak-anaknya. Misalnya, elemen sebaris akan menjadi elemen blok dengan lebar penuh; jika mereka memiliki margin, itu juga akan runtuh.
zupa
9

Setiap browser berbasis webkit harus mendukung properti -webkit-margin-collapse . Ada juga subproperti yang hanya mengaturnya untuk margin atas atau bawah. Anda bisa memberikannya nilai runtuh (default), buang (set margin ke 0 jika ada margin tetangga), dan pisahkan (mencegah runtuhnya margin).

Saya telah menguji bahwa ini berfungsi pada Chrome dan Safari versi 2014. Sayangnya, saya tidak berpikir ini akan didukung di IE karena tidak didasarkan pada webkit.

Baca Referensi CSS Safari Apple untuk penjelasan lengkap.

Jika Anda memeriksa halaman ekstensi webkit Mozilla CSS , mereka mencantumkan properti ini sebagai milik dan merekomendasikan untuk tidak menggunakannya. Ini karena mereka kemungkinan tidak akan masuk ke CSS standar dalam waktu dekat dan hanya browser berbasis webkit yang akan mendukungnya.

Dan Carter
sumber
Ini bagus karena membantu kami mengatasi ketidakkonsistenan dalam cara Safari dan Chrome menangani margin.
bjudson
8

Saya tahu bahwa ini adalah posting yang sangat lama tetapi hanya ingin mengatakan bahwa menggunakan flexbox pada elemen induk akan menonaktifkan margin collapsing untuk elemen turunannya.

Genzo
sumber
Tidak hanya untuk elemen anaknya - itu juga mencegah margin yang runtuh antara orang tua dan anak pertama dan terakhir.
Sven Marnach
2

Saya memiliki masalah yang sama dengan runtuhnya margin karena orang tua telah positionmenetapkan ke relatif. Berikut adalah daftar perintah yang dapat Anda gunakan untuk menonaktifkan margin collapsing.

DI SINI ADALAH PEMAIN UNTUK UJI

Hanya mencoba untuk menetapkan setiap parent-fix*kelas untuk div.containerelemen, atau kelas apa pun children-fix*untuk div.margin. Pilih salah satu yang paling sesuai dengan kebutuhan Anda.

Kapan

  • Margin runtuh adalah dinonaktifkan ,div.absolute dengan latar belakang merah akan diposisikan di bagian paling atas halaman.
  • margin yang runtuh div.absolute akan diposisikan pada koordinat Y yang sama dengandiv.margin

html, body { margin: 0; padding: 0; }

.container {
  width: 100%;
  position: relative;
}

.absolute {
  position: absolute;
  top: 0;
  left: 50px;
  right: 50px;
  height: 100px;
  border: 5px solid #F00;
  background-color: rgba(255, 0, 0, 0.5);
}

.margin {
  width: 100%;
  height: 20px;
  background-color: #444;
  margin-top: 50px;
  color: #FFF;
}

/* Here are some examples on how to disable margin 
   collapsing from within parent (.container) */
.parent-fix1 { padding-top: 1px; }
.parent-fix2 { border: 1px solid rgba(0,0,0, 0);}
.parent-fix3 { overflow: auto;}
.parent-fix4 { float: left;}
.parent-fix5 { display: inline-block; }
.parent-fix6 { position: absolute; }
.parent-fix7 { display: flex; }
.parent-fix8 { -webkit-margin-collapse: separate; }
.parent-fix9:before {  content: ' '; display: table; }

/* Here are some examples on how to disable margin 
   collapsing from within children (.margin) */
.children-fix1 { float: left; }
.children-fix2 { display: inline-block; }
<div class="container parent-fix1">
  <div class="margin children-fix">margin</div>
  <div class="absolute"></div>
</div>

Berikut adalah jsFiddle dengan contoh yang dapat Anda edit

Buksy
sumber
1

Di browser yang lebih baru (tidak termasuk IE11), solusi sederhana untuk mencegah runtuhnya margin orangtua-anak adalah dengan menggunakannya display: flow-root. Namun, Anda masih membutuhkan teknik lain untuk mencegah runtuhnya elemen yang berdekatan.

DEMO (sebelumnya)

.parent {
  background-color: grey;
}

.child {
  height: 16px;
  margin-top: 16px;
  margin-bottom: 16px;
  background-color: blue;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>

DEMO (setelah)

.parent {
  display: flow-root;
  background-color: grey;
}

.child {
  height: 16px;
  margin-top: 16px;
  margin-bottom: 16px;
  background-color: blue;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>

Chuanqi Sun
sumber
0

Untuk informasi Anda, Anda dapat menggunakan kotak tetapi dengan efek samping :)

.parent {
  display: grid
}
Whisher
sumber