Come disabilitare il collasso dei margini?


202

C'è un modo per disabilitare del tutto il collasso dei margini? Le uniche soluzioni che ho trovato (con il nome di "uncollapsing") prevedono l'utilizzo di un bordo 1px o di un'imbottitura 1px. Lo trovo inaccettabile: il pixel estraneo complica i calcoli senza una buona ragione. C'è un modo più ragionevole per disabilitare questo margine di collasso?


4
Usa il layout Flex o Grid, dove non esiste il collasso dei margini: stackoverflow.com/a/46496701/3597276
Michael Benjamin

Dai semplicemente un valore agli elementi margin-bottomma lascia margin-topcome 0.
Dan Bray il

Ho creato un pacchetto per semplificare il calcolo: npmjs.com/package/collapsed-margin
Owen M

Risposte:


255

Esistono due tipi principali di collasso dei margini:

  • Margini collassanti tra elementi adiacenti
  • Margini collassanti tra elementi padre e figlio

L'uso di un'imbottitura o di un bordo impedirà il collasso solo in quest'ultimo caso. Inoltre, qualsiasi valore overflowdiverso dal suo default ( visible) applicato al genitore impedirà il collasso. Pertanto, entrambi overflow: autoe overflow: hiddenavranno lo stesso effetto. Forse l'unica differenza durante l'utilizzo hiddenè la conseguenza non intenzionale di nascondere il contenuto se il genitore ha un'altezza fissa.

Altre proprietà che, una volta applicate al genitore, possono aiutare a correggere questo comportamento sono:

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

Puoi testarli tutti qui: http://jsfiddle.net/XB9wX/1/ .

Dovrei aggiungere che, come al solito, Internet Explorer è l'eccezione. Più specificamente, in IE 7 i margini non si riducono quando viene specificato un tipo di layout per l'elemento padre, ad esempio width.

Fonti: articolo di Sitepoint Margini collassanti


1
nota che anche il riempimento può influire su questo se non è un valore zero
Mladen Janjetovic,

3
Si noti che overflow: autopuò causare la visualizzazione di barre di scorrimento nell'elemento genitore, anziché consentire l'overflow del contenuto di overflow come da overflow: visible.
Leo,

"overflow: auto" non sembra funzionare in Chrome v44.
tkane2000,

3
Grazie per la visualizzazione: blocco in linea, mi ha salvato :)
alexcasalboni

3
Qualsiasi valore flexdiverso dal suo valore predefinito disabiliterà anche il collasso del margine
Oly

60

Per questo puoi anche usare il buon vecchio micro clearfix.

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

Vedi violino aggiornato: http://jsfiddle.net/XB9wX/97/


Ho trasformato la mia risposta in un wiki della community. Sentiti libero di estenderlo con la tua risposta. Grazie.
hqcasanova,

3
Non capisco, quando vedo quell'esempio i margini stanno crollando (solo 10px di spazio verticale tra i div invece di 20px)
Andy,

1
Questo aiuta solo a rimuovere il collasso tra fratelli a cui è stato applicato questo clearfix. Ho fatto l'esempio per dimostrarlo: jsfiddle.net/dpyuyg07 --- e anche questa non è l'intera storia. Rimuove solo il collasso dei margini derivanti dai figli degli elementi in cui hai applicato quella correzione. Se si aggiungesse un margine sul contenitore stesso, i margini verrebbero comunque collassati, come si può vedere in questo fork: jsfiddle.net/oew7qsjx
NicBright,

4
Posso dirlo in modo ancora più preciso: il metodo clearfix impedisce solo il collasso dei margini tra genitori e figli. Non influisce sul collasso tra fratelli adiacenti.
NicBright,

Penso di capire ora la tendenza di Bootstrap a riempire il DOM :beforee gli :afterelementi. Ora ho aggiunto questa regola al mio foglio di stile: div:before, div:after{content: ' '; display: table;}. Fantastico. Improvvisamente le cose iniziano a comportarsi come previsto.
Stijn de Witt,

60

Un trucco per disabilitare il collasso dei margini che non ha alcun impatto visivo, per quanto ne so, è impostare il riempimento del genitore su 0.05px:

.parentClass {
    padding: 0.05px;
}

L'imbottitura non è più 0, quindi il collasso non avverrà più, ma allo stesso tempo l'imbottitura è abbastanza piccola da rendere visivamente arrotondata a 0.

Se si desidera un'altra imbottitura, applicare l'imbottitura solo nella "direzione" in cui non si desidera il collasso dei margini, ad esempio padding-top: 0.05px;.

Esempio funzionante:

.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>

Modifica: modificato il valore da 0.1a 0.05. Come ha detto Chris Morgan in un commento qui sotto, e da questo piccolo test , sembra che Firefox prenda 0.1pxin considerazione l' imbottitura. 0.05pxTuttavia , sembra fare il trucco.


2
Questa è la mia soluzione preferita Potresti anche includerlo come stile predefinito. Perchè no? *{padding-top:0.1px}. Siamo sicuri che funzioni in tutti i browser?
Nick Manning,

Finora ha funzionato abbastanza bene per me, ma non pretendo di averlo testato a fondo nella maggior parte dei browser.
Nicu Surdu,

2
Soluzione molto bella, sembra funzionare come previsto sulla maggior parte dei browser. Grazie per averlo condiviso!
wiredolphin,

1
Questa è una soluzione dubbia in quanto non aggiunge pixel supplementari in diverse circostanze, a causa di display ad alta risoluzione e calcoli subpixel. (Firefox ha realizzato layout subpixel per anni, credo che altri browser abbiano seguito relativamente di recente l'esempio.)
Chris Morgan,

0.05pxsembra ancora una scelta specifica, non un numero di trucchi del browser casuale, preferirei 0.01px.
Volker E.

22

overflow:hidden impedisce il collasso dei margini, ma non è privo di effetti collaterali - vale a dire ... nasconde il troppo pieno.

A parte questo e quello che hai menzionato, devi solo imparare a conviverci e imparare per questo giorno quando sono effettivamente utili (arriva ogni 3-5 anni).


Ho trasformato la mia risposta in un wiki della community. Penso di aver trattato l'effetto collaterale che hai citato nelle ultime due righe del secondo paragrafo: forse l'unica differenza quando si usa nascosto è la conseguenza non intenzionale di nascondere il contenuto se il genitore ha un'altezza fissa . Ma se ritieni che necessiti di ulteriori chiarimenti, non esitare a contribuire. Grazie.
hqcasanova,

7
overflow: autoè utile per impedire l'overflow nascosto e impedire comunque il collasso dei margini.
Gavin,

@Gavin, la overflow:auto;mia area di contenuto ha ottenuto una barra di scorrimento in alcune pagine.
Reed,

13

In realtà, ce n'è uno che funziona perfettamente:

display: flessibile; direzione flessibile: colonna;

purché tu possa vivere supportando solo IE10 e versioni successive

.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>


Affinché ciò funzioni come una soluzione generica, è necessario aggiungere un extra <div>all'interno del .container, altrimenti .containercontrollerà il modello a scatola dei suoi figli. Ad esempio, gli elementi incorporati diventeranno elementi di blocco a larghezza piena; se hanno margini, anche quelli saranno ridotti al margine.
Zupa,

9

Ogni browser basato su webkit dovrebbe supportare le proprietà -webkit-margin-collapse. Ci sono anche proprietà secondarie per impostarlo solo per il margine superiore o inferiore. Puoi assegnargli i valori di compressione (impostazione predefinita), scarta (imposta il margine su 0 se esiste un margine adiacente) e separa (impedisce la compressione del margine).

Ho provato che funziona con le versioni 2014 di Chrome e Safari. Sfortunatamente, non penso che questo sarebbe supportato in IE perché non è basato su webkit.

Leggi il riferimento CSS Safari di Apple per una spiegazione completa.

Se controlli la pagina delle estensioni webkit CSS di Mozilla , queste proprietà sono elencate come proprietarie e raccomandano di non usarle. Questo perché probabilmente non entreranno presto nei CSS standard e solo i browser basati su webkit li supporteranno.


Questo è utile perché ci aiuta a risolvere un'incoerenza nel modo in cui Safari e Chrome gestiscono i margini.
bjudson,

8

So che questo è un post molto vecchio, ma volevo solo dire che l'uso di flexbox su un elemento genitore disabiliterebbe il collasso dei margini per i suoi elementi figlio.


Non solo per i suoi elementi figlio, impedisce anche il collasso del margine tra genitore e primo e ultimo figlio.
Sven Marnach,

2

Ho avuto un problema simile con il collasso del margine a causa del genitore position impostato su relativo. Ecco un elenco di comandi che è possibile utilizzare per disabilitare il collasso dei margini.

ECCO IL PARCO GIOCHI DA PROVA

Prova ad assegnare qualsiasi parent-fix*classe div.containerall'elemento o qualsiasi classe children-fix*a div.margin. Scegli quello più adatto alle tue esigenze.

quando

  • il collasso dei margini è disabilitato , div.absolutecon lo sfondo rosso posizionato nella parte superiore della pagina.
  • il margine che sta crollando div.absolute verrà posizionato sulla stessa coordinata Y didiv.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>

Ecco jsFiddle con l'esempio che puoi modificare


1

Nel browser più recente (escluso IE11), è necessario utilizzare una semplice soluzione per impedire il collasso del margine genitore-figlio display: flow-root. Tuttavia, sarebbero comunque necessarie altre tecniche per impedire il collasso dell'elemento adiacente.

DEMO (prima)

.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 (dopo)

.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>


0

Per tua informazione, puoi usare la griglia ma con effetti collaterali :)

.parent {
  display: grid
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.