Margin-Top spingere il div esterno verso il basso


126

Ho un div dell'intestazione come primo elemento nel mio div wrapper, ma quando aggiungo un margine superiore a un h1 all'interno del div dell'intestazione, spinge l'intero div dell'intestazione verso il basso. Mi rendo conto che ciò accade ogni volta che applico un margine superiore al primo elemento visibile in una pagina.

Ecco un frammento di codice di esempio. Grazie!

div#header{
	width: 100%;
	background-color: #eee;
	position: relative;
}

div#header h1{
	text-align: center;
	width: 375px;
	height: 50px;
	margin: 50px auto;
	font-size: 220%;
	background: url('../../images/name_logo.png') no-repeat;
}
<div id="header">
	<h1>Title</h1>
	<ul id="navbar"></ul>
</div>

Risposte:


193

inserisci overflow:autoil genitore div
vedi di più in questo link


29
overflow:hiddenè migliore per il 90% dei casi.
vsync,

1
Perché traboccare: nascosto sarebbe meglio?
peterchon,

5
@peterchon - perché auto può causare barre di scorrimento
vsync

3
non funziona più, la risposta di @ SW4 in questo link è migliore
am05mhz

1
overflow: hiddeno overflow: autopuò causare effetti collaterali indesiderati, alcuni dei quali potrebbero non essere visibili a prima vista. Ho scoperto che cambiare marginper paddingfare il trucco, come suggerisce la risposta di seguito. Tuttavia, non capisco perché l'intero problema si verifichi.
Gilad Barner,

34

Non ho una spiegazione solida sul motivo per cui questo accade, ma ho riparato questo cambiando la top-margina top-padding, o l'aggiunta display: inline-blockallo stile elemento.

EDIT: questa è la mia teoria

Ho la sensazione che abbia qualcosa a che fare con il modo in cui i margini vengono collassati (combinati).

dai margini di collasso del W3C :

In questa specifica, l'espressione dei margini di compressione significa che i margini adiacenti (nessun contenuto non vuoto, aree di riempimento o bordo o spazio separati) di due o più caselle (che possono essere uno accanto all'altro o nidificati) si combinano per formare un margine singolo .

La mia teoria è che dal momento che il tuo primo elemento è vicino al corpo, i due margini si combinano e vengono applicati al corpo: questo costringe il contenuto del corpo a iniziare al di sotto del margine compresso applicato in conformità con il modello a scatola .

Ci sono situazioni in cui i margini non collassano con i quali potrebbe valere la pena giocarci (da Collapsing Margins ):

* floated elements
* absolutely positioned elements
* inline-block elements
* elements with overflow set to anything other than visible (They do not collapse margins with their children.)
* cleared elements (They do not collapse their top margins with their parent block’s bottom margin.)
* the root element

3
Inoltre, il riempimento o il bordo dell'elemento con margine compresso (quello interno) non lo comprimono.
Anonimo il

Questo ha funzionato per me - avevo elementi assoluti (un menu a discesa) nel mio contenitore, quindi trabocco: l'auto non ha funzionato.
mwilcox,

17

Questi sono alcuni dei modi per evitare il collasso dei margini tra elementi genitore-figlio. Usa quello che si adatta meglio al resto del tuo stile:

  • Impostato displaysu un valore diverso dablock .
  • Impostato floatsu un valore diverso danone .
  • Rimuovere il margine e utilizzare invece padding. Ad esempio, se lo fosse margin-top: 10px, sostituirlo conpadding-top: 10px; .
  • Rimuovere il margine, e usare al posto position( absoluteo relative) con gli attributi top, bottome così via, ad esempio se si ha margin-top: 10px, sostituirlo conposition: relative; top: 10px; .
  • Aggiungi a paddingo a bordernel lato in cui i margini stanno collassando, all'elemento principale . Il bordo può essere 1px e trasparente.
  • Impostare overflowun valore diverso da visibleal genitore elemento.

5

So che questo è un vecchio problema, l'ho riscontrato molte volte. Il problema è che tutte le correzioni qui sono hack che potrebbero avere conseguenze indesiderate.

Prima di tutto, c'è una semplice spiegazione per il problema alla radice. A causa del modo in cui funziona il collasso dei margini, se il primo elemento all'interno di un contenitore ha un margine superiore, quel margine superiore viene effettivamente applicato al contenitore padre stesso. Puoi testarlo da solo procedendo come segue:

<div>
    <h1>Test</h1>
</div>

In un debugger, aprilo e passa il mouse sul div. Noterai che il div stesso è effettivamente posizionato dove si ferma il margine superiore dell'elemento H1 . Questo comportamento è inteso dal browser.

Quindi c'è una soluzione semplice a questo senza dover ricorrere a strani hack, come fanno la maggior parte dei post qui (nessun insulto previsto, è solo la verità) - semplicemente tornare alla spiegazione originale - ...if the first element inside a container has a top margin...- A seguito di ciò, avresti quindi bisogno il primo elemento in un contenitore su NOT ha un margine superiore. Va bene, ma come si fa senza aggiungere elementi che non interferiscono semanticamente con il documento?

Facile! Gli pseudo-elementi! Puoi farlo tramite una classe o un mixin predefinito. Aggiungi uno :beforepseudo-elemento:

CSS tramite una classe:

.top-margin-fix:before {   
    content: ' ';
    display: block;
    width: 100%;
    height: .0000001em;
}

Con questo, seguendo l'esempio di markup sopra riportato, modificheresti il ​​div in quanto tale:

<div class="top-margin-fix">
    <h1>Test</h1>
</div>

Perché funziona?

Il primo elemento in un contenitore, se non ha margine superiore, imposta la posizione dell'inizio del margine superiore dell'elemento successivo. Aggiungendo uno :beforepseudo-elemento, il browser aggiunge effettivamente un elemento non semantico (in altre parole, buono per SEO) nel contenitore principale prima del primo elemento.

D. Perché l'altezza: .0000001em?

A. È necessaria un'altezza per consentire al browser di spingere verso il basso l'elemento del margine. Questa altezza è effettivamente zero, ma ti consentirà comunque di aggiungere imbottitura al contenitore padre stesso. Dato che è effettivamente zero, non avrà alcun effetto sul layout del contenitore. Bellissimo.

Ora puoi aggiungere una classe (o meglio, in SASS / LESS, un mixin!) Per risolvere questo problema invece di aggiungere strani stili di visualizzazione che causeranno conseguenze inattese quando vuoi fare altre cose con i tuoi elementi, eliminando deliberatamente i margini sugli elementi e / o sostituendolo con un'imbottitura o strani stili di posizione / float che in realtà non sono destinati a risolvere questo problema.


2
.0000001em viene arrotondato a zero in IE11, interrompendo la correzione. Quando lo cambio in .01em funziona però.
Esger,

1
Immagino che .01em sarà sufficiente per essere ancora effettivamente zero. Buon punto. Il lato positivo, ora che è il 2018, molti di noi abbandoneranno presto il supporto per IE11, specialmente con il recente annuncio che MS tornerà a costruire un nuovo browser (tranne questa volta, basato sul cromo, il che significa che - teoricamente - non farà assolutamente schifo). : D
dudewad,

2

display: flexfunzionerà in questo caso. Dai un elemento genitore display: flex;e poi dai margine secondo il tuo requisito al h1tag.


0

Incontrare questo problema oggi.

overflow: hidden non ha funzionato come previsto quando ho seguito più elementi.

Quindi ho provato a cambiare la proprietà display del div del genitore e ho display: flexfunzionato !!!

Spero che questo possa aiutare qualcuno. :)


0

L'aggiunta di un po 'di padding alla parte superiore dell'elemento genitore può risolvere questo problema.

.parent{
  padding-top: 0.01em;
}

Ciò è utile se è necessario che un elemento all'interno del genitore sia visibile all'esterno dell'elemento genitore, come se si stesse creando un effetto di sovrapposizione.


0

Ciò accade a causa del collasso del margine. Quando l'elemento figlio tocca il limite dell'elemento padre e uno qualsiasi di essi viene applicato con i margini, allora:

  1. Il margine più grande vincerà (applicato).

  2. se qualcuno di loro ha un margine, entrambi condivideranno lo stesso.

soluzioni

  1. applica il bordo al genitore che separa genitore e figlio.
  2. applica il riempimento al genitore che separa genitore e figlio.
  3. applica overflow piuttosto che visibile sul genitore.
  4. usare prima o dopo per creare un elemento virtuale nel div parent che può differire da child e parent applicati a margine.
  5. creare un elemento html tra figlio applicato a margine e padre può anche separarli.
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.