Margin-Top wciśnij zewnętrzną div w dół


126

Mam element div nagłówka jako pierwszy element mojego elementu div wrapper, ale kiedy dodam górny margines do h1 wewnątrz elementu div nagłówka, przesuwa cały element div nagłówka w dół. Zdaję sobie sprawę, że dzieje się tak za każdym razem, gdy nakładam górny margines na pierwszy widoczny element na stronie.

Oto przykładowy fragment kodu. Dzięki!

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>

Odpowiedzi:


193

umieść overflow:autorodzica div
zobacz więcej w tym linku


29
overflow:hiddenjest lepsza w 90% przypadków.
vsync

1
Dlaczego przepełnienie: ukryte byłoby lepsze?
peterchon

5
@peterchon - ponieważ auto może powodować paski przewijania
vsync

3
już nie działa, odpowiedź @ SW4 w tym linku jest lepsza
am05mhz

1
overflow: hiddenlub overflow: automoże powodować niepożądane skutki uboczne, z których niektórych możesz nie zauważyć na pierwszy rzut oka. Przekonałem się, że zmiana marginna paddingzałatwia sprawę, jak sugeruje odpowiedź poniżej. Nadal nie rozumiem jednak, dlaczego tak się dzieje.
Gilad Barner

34

Nie mam solidne wyjaśnienie, dlaczego tak się dzieje, ale Naprawiłem to zmieniając top-marginsię top-padding, czy dodanie display: inline-blockdo stylu elementu.

EDYCJA: To moja teoria

Mam wrażenie, że ma to coś wspólnego z tym, jak marginesy są zwijane (łączone).

z W3C Collapsing Margins :

W tej specyfikacji wyrażenie zwijane marginesy oznacza, że ​​sąsiednie marginesy (bez niepustej treści, wypełnienia lub obszarów obramowania lub odstępu) dwóch lub więcej pól (które mogą być obok siebie lub zagnieżdżone) łączą się, tworząc pojedynczy margines .

Moja teoria mówi, że ponieważ twój pierwszy element znajduje się obok ciała, dwa marginesy łączą się i są nakładane na ciało: zmusza to zawartość ciała do rozpoczęcia poniżej zastosowanego zwiniętego marginesu zgodnie z modelem pudełkowym .

Istnieją sytuacje, w których marginesy nie zapadają się, co może być warte zabawy (z 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
Również dopełnienie lub obramowanie elementu ze zwiniętym marginesem (wewnętrznym) spowoduje cofnięcie zwinięcia elementu.
Anonimowy

U mnie to zadziałało - miałem w kontenerze elementy absolutne (rozwijane), więc przepełnienie: auto nie działało.
mwilcox

17

Oto niektóre sposoby uniknięcia zwijania marginesów między elementami rodzic-dziecko. Użyj tego, który lepiej pasuje do reszty Twojej stylizacji:

  • Ustaw displayinny niż block.
  • Ustaw floatinny niż none.
  • Usuń margines i użyj zamiast tego padding. Na przykład, jeśli tak margin-top: 10px, zamień na padding-top: 10px;.
  • Usuń margines i używać zamiast position( absolutelub relative) z atrybutami top, bottomitd Na przykład jeśli miał margin-top: 10px, zastąpić position: relative; top: 10px;.
  • Dodaj znak paddinglub a borderpo stronie, w której marginesy są zwijane, do elementu nadrzędnego . Obramowanie może mieć rozmiar 1 piksela i być przezroczyste.
  • Ustawić overflowna wartość inną niż visibledo dominującego elementu.

5

Wiem, że to stary problem, zetknąłem się z nim wiele razy. Problem polega na tym, że wszystkie poprawki tutaj to hacki, które potencjalnie mogą mieć niezamierzone konsekwencje.

Po pierwsze, istnieje proste wyjaśnienie problemu źródłowego. Ze względu na sposób, w jaki działa zwijanie marginesów, jeśli pierwszy element wewnątrz kontenera ma górny margines, ten górny margines jest skutecznie stosowany do samego kontenera nadrzędnego. Możesz to sprawdzić samodzielnie, wykonując następujące czynności:

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

W debugerze otwórz to i najedź na div. Zauważysz, że sam element div jest faktycznie umieszczony w miejscu, w którym kończy się górny margines elementu H1 . Takie zachowanie jest zamierzone przez przeglądarkę.

Jest więc łatwa naprawa bez konieczności uciekania się do dziwnych hacków, jak to ma miejsce w większości postów tutaj (bez obelg, to tylko prawda) - po prostu wróć do pierwotnego wyjaśnienia - ...if the first element inside a container has a top margin...- Po tym, będziesz potrzebować pierwszy element w kontenerze NIE ma górnego marginesu. OK, ale jak to zrobić bez dodawania elementów, które nie kolidują semantycznie z dokumentem?

Łatwo! Pseudoelementy! Możesz to zrobić za pomocą klasy lub wstępnie zdefiniowanej mieszanki. Dodaj :beforepseudoelement:

CSS poprzez klasę:

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

W ten sposób, postępując zgodnie z powyższym przykładem znaczników, zmodyfikowałbyś swój div jako taki:

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

Dlaczego to działa?

Pierwszy element w kontenerze, jeśli nie ma górnego marginesu, ustala położenie początku górnego marginesu następnego elementu. Dodając :beforepseudoelement, przeglądarka faktycznie dodaje element niesemantyczny (innymi słowy, dobry dla SEO) do kontenera nadrzędnego przed pierwszym elementem.

P: Dlaczego wysokość: .0000001em?

A. Aby przeglądarka przesunęła element marginesu w dół, wymagana jest wysokość. Ta wysokość jest efektywnie równa zero, ale nadal umożliwia dodanie wypełnienia do samego kontenera nadrzędnego. Ponieważ jest to praktycznie zero, nie będzie miało to również wpływu na układ kontenera. Piękny.

Teraz możesz dodać klasę (lub lepiej, w SASS / LESS, mixin!), Aby rozwiązać ten problem, zamiast dodawać dziwne style wyświetlania, które będą powodować nieoczekiwane konsekwencje, gdy chcesz robić inne rzeczy z elementami, celowo eliminując marginesy na elementach i / lub zastąpienie go dopełnieniem lub dziwnymi stylami pozycji / swobodnych, które tak naprawdę nie mają na celu rozwiązania tego problemu.


2
.0000001em jest naprawdę zaokrąglany do zera w IE11, co psuje poprawkę. Kiedy zmieniam to na .01em to działa.
Esger,

1
Wyobrażam sobie, że 0,01em wystarczy, aby nadal skutecznie wynosić zero. Słuszna uwaga. Z drugiej strony, teraz, gdy mamy 2018 rok, wielu z nas wkrótce zrezygnuje ze wsparcia dla IE11, szczególnie w związku z niedawnym ogłoszeniem, że MS po raz kolejny będzie budować nową przeglądarkę (poza tym razem opartą na chromie, co oznacza - teoretycznie) - nie będzie do niczego). : D
dudewad

2

display: flexzadziała w tym przypadku. Podaj element nadrzędny, display: flex;a następnie podaj margines zgodnie z wymaganiami h1tagu.


0

Zajrzyj do tego problemu już dziś.

overflow: hidden nie działało zgodnie z oczekiwaniami, gdy śledzono więcej elementów.

Więc spróbowałem zmienić właściwość wyświetlania nadrzędnego div i display: flexzadziałałem !!!

Mam nadzieję, że to może komuś pomóc. :)


0

Dodanie odrobiny wypełnienia do górnej części elementu nadrzędnego może rozwiązać ten problem.

.parent{
  padding-top: 0.01em;
}

Jest to przydatne, jeśli chcesz, aby element wewnątrz elementu nadrzędnego był widoczny poza elementem nadrzędnym, na przykład w przypadku tworzenia efektu nakładania się.


0

Dzieje się tak z powodu załamania marginesu. Kiedy element potomny dotknie granicy elementu rodzica i którykolwiek z nich zostanie zastosowany z marginesami, to:

  1. Wygra marża, która jest największa (zastosowana).

  2. jeśli którykolwiek z nich ma margines, obaj będą mieli taki sam margines.

Rozwiązania

  1. zastosuj obramowanie do rodzica, co powoduje oddzielenie rodzica i dziecka.
  2. zastosuj dopełnienie do rodzica, co powoduje oddzielenie rodzica i dziecka.
  3. zastosuj przepełnienie zamiast widocznego na rodzicu.
  4. użyj przed lub po, aby utworzyć element wirtualny w nadrzędnym div, który może różnić się marginesem zastosowanym podrzędnym i nadrzędnym.
  5. utworzyć jeden element html między dzieckiem a rodzicem zastosowanym marginesem może również je oddzielić.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.