Jak działają ujemne marże w CSS i dlaczego (margin-top: -5! = Margin-bottom: 5)?

108

Typową sztuczką związaną z pozycjonowaniem pionowym jest użycie następującego kodu CSS:

.item {
    position:absolute;
    top:50%;
    margin-top:-8px; /* half of height */
    height: 16px;
}

W widoku danych, podobnie jak w Chrome, widać to:

wprowadź opis obrazu tutaj

Jednak nie ma widocznego marginesu po najechaniu kursorem na element, tj. Margines znajduje się „poza” obramowaniem i można go zwizualizować. Ale ujemne marże nie pojawiają się. Jak wyglądają i co sprawia, że ​​jest inny?

Dlaczego margin-top:-8px nie jest taki sam jakmargin-bottom:8px ?

Jak więc działają ujemne marże i jaka jest za nimi intuicja. W jaki sposób „podbijają” (w przypadku margin-top < 0) przedmiotu?

PhD
źródło

Odpowiedzi:

89

Ujemne marginesy są ważne w CSS, a zrozumienie ich (zgodnego) zachowania opiera się głównie na modelu pudełkowym i zwijaniu marginesów. Chociaż niektóre scenariusze są bardziej złożone, po przestudiowaniu specyfikacji można uniknąć wielu typowych błędów.

Na przykład, renderowanie twojego przykładowego kodu jest oparte na specyfikacji CSS, jak opisano przy obliczaniu wysokości i marginesów dla absolutnie pozycjonowanych niezastępowanych elementów .

Gdybym miał zrobić graficzną reprezentację, prawdopodobnie wybrałbym coś takiego (nie skalując):

ujemny górny margines

Pole marginesu utracone 8pxna górze, jednak nie wpływa to na zawartość i pola wypełniające . Ponieważ element jest pozycjonowany absolutnie, przesunięcie elementu o 8 pikseli w górę nie powoduje żadnych dalszych zakłóceń w układzie; ze statyczną zawartością w przepływie nie zawsze tak jest.

Premia:

Nadal trzeba przekonywać, że czytanie specyfikacji jest droga (w przeciwieństwie do artykułów takich jak ten )? Widzę, że próbujesz wyśrodkować element w pionie, więc dlaczego musisz ustawić, a nie ?margin-top:-8px;margin-top:-50%;

Cóż, centrowanie w pionie w CSS jest trudniejsze niż powinno . W przypadku ustawiania nawet górnego lub dolnego marginesu w%, wartość jest obliczana jako procent zawsze w stosunku do szerokości bloku zawierającego . Jest to raczej powszechna pułapka, a dziwactwo jest rzadko opisywane poza dokumentami w3

ov
źródło
84

Postaram się wyjaśnić to wizualnie:

/**
 * explaining margins
 */

body {
  padding: 3em 15%
}

.parent {
  width: 50%;
  width: 400px;
  height: 400px;
  position: relative;
  background: lemonchiffon;
}

.parent:before,
.parent:after {
  position: absolute;
  content: "";
}

.parent:before {
  top: 0;
  bottom: 0;
  left: 50%;
  border-left: dashed 1px #ccc;
}

.parent:after {
  left: 0;
  right: 0;
  top: 50%;
  border-top: dashed 1px #ccc;
}

.child {
  width: 200px;
  height: 200px;
  background: rgba(200, 198, 133, .5);
}

ul {
  padding: 5% 20px;
}

.set1 .child {
  margin: 0;
  position: relative;
}

.set2 .child {
  margin-left: 75px;
  position: relative;
}

.set3 .child {
  margin-left: -75px;
  position: relative;
}


/* position absolute */

.set4 .child {
  top: 50%;
  left: 50%;
  margin: 0;
  position: absolute;
}

.set5 .child {
  top: 50%;
  left: 50%;
  margin-left: 75px;
  position: absolute;
}

.set6 .child {
  top: 50%; /* level from which margin-top starts 
	- downwards, in the case of a positive margin
	- upwards, in the case of a negative margin	
	*/
  left: 50%; /* level from which margin-left starts 
	- towards right, in the case of a positive margin
	- towards left, in the case of a negative margin	
	*/
  margin: -75px;
  position: absolute;
}
<!-- content to be placed inside <body>…</body> -->
<h2><code>position: relative;</code></h2>
<h3>Set 1</h3>
<div class="parent set 1">
  <div class="child">
    <pre>
.set1 .child {
  margin: 0;
  position: relative;
}
		</pre>
  </div>
</div>

<h3>Set 2</h3>
<div class="parent set2">
  <div class="child">
    <pre>
.set2 .child {
  margin-left: 75px;
  position: relative;
}
		</pre>
  </div>
</div>

<h3>Set 3</h3>
<div class="parent set3">
  <div class="child">
    <pre>
.set3 .child {
  margin-left: -75px;
  position: relative;
}
		</pre>
  </div>
</div>

<h2><code>position: absolute;</code></h2>

<h3>Set 4</h3>
<div class="parent set4">
  <div class="child">
    <pre>
.set4 .child {
  top: 50%;
  left: 50%;
  margin: 0;
  position: absolute;
}
		</pre>
  </div>
</div>

<h3>Set 5</h3>
<div class="parent set5">
  <div class="child">
    <pre>
.set5 .child {
  top: 50%;
  left: 50%;
  margin-left: 75px;
  position: absolute;
}
		</pre>
  </div>
</div>

<h3>Set 6</h3>
<div class="parent set6">
  <div class="child">
    <pre>
.set6 .child {
  top: 50%;
  left: 50%;
  margin: -75px;
  position: absolute;
}
		</pre>
  </div>
</div>

Ana
źródło
33

Margines to odstępy na zewnątrz elementu, tak samo jak odstępy wewnątrz elementu.

Ustawienie dolnego marginesu wskazuje, jaką odległość chcesz poniżej bieżącego bloku. Ustawienie ujemnego górnego marginesu wskazuje, że chcesz ujemny odstęp nad blokiem. Negatywne odstępy mogą same w sobie być mylącym pojęciem, ale tak jak dodatni górny margines wypycha zawartość w dół, ujemny górny margines przyciąga zawartość.

David Hedlund
źródło
2
+1 Podoba mi się twoja odpowiedź. Można to poprawić, wstrzykując słowa onseti offset. To prawda, że ​​tak wiele osób zawsze używa słowa offset( negatywne ), kiedy ma na myśli onset( pozytywne ). Ta wiadomość ulegnie samozniszczeniu, jeśli zaktualizujesz swoją odpowiedź. Twoje zdrowie!
arttronics
1
O co chodzi margin-bottom: -8px;? Dlaczego margin-bottom:-8pxnie jest taki sam jak margin-top:-8px?
Rick
27

Górny margines równy -8 pikseli oznacza, że ​​będzie on o 8 pikseli wyższy niż w przypadku marginesu 0.

Dno marginesu wynoszące 8 pikseli oznacza, że ​​element pod nim będzie o 8 pikseli niżej niż gdyby miał margines 0.

Rich Bradshaw
źródło
1
Starałem się tylko uprościć sprawę, ale zgadzam się, to jest prawdopodobnie najgorsza z moich odpowiedzi!
Rich Bradshaw,
2
Myślę, że odpowiedź jest całkiem dobra. Nie ma pożytku z wysoce technicznych odpowiedzi, których połowa z nas nie rozumie.
Number945
1
O co chodzi margin-bottom: -8px;? Dlaczego margin-bottom:-8pxnie jest taki sam jak margin-top:-8px?
Rick
22

dobre uwagi już tutaj przedstawione, ale chociaż istnieje wiele informacji o tym, jak renderowanie marginesów jest wykonywane przez przeglądarkę, dlaczego nie ma jeszcze pełnej odpowiedzi:

„Dlaczego margin-top: -8px to nie to samo co margin-bottom: 8px?”

moglibyśmy również zapytać:

Dlaczego dodatni dolny margines nie „podbija” poprzedzających elementów, podczas gdy dodatni górny margines „nie podnosi” kolejnych elementów?

więc widzimy, że istnieje różnica w renderowaniu marginesów w zależności od strony, po której są one stosowane - marginesy górne (i lewe) różnią się od marginesów dolnych (i prawych).

rzeczy stają się jaśniejsze, gdy przyjrzymy się (uproszczonemu), jak style są stosowane przez przeglądarkę: elementy są renderowane z góry na dół w rzutni, zaczynając od lewego górnego rogu (na razie trzymajmy się renderowania pionowego, pamiętając, że poziomy traktuje się tak samo).

rozważ następujący html:

<div class="box1"></div>
<div class="box2"></div>
<div class="box3"></div>

Analogicznie do ich pozycji w kodzie, te trzy pola pojawiają się w przeglądarce w stosie „od góry do dołu” ( mówiąc prostym, nie będziemy tutaj rozważać orderwłaściwości modułu css3 „flex-box” ). tak więc za każdym razem, gdy style są stosowane do pola 3, pozycje poprzedzającego elementu (dla pola 1 i 2) zostały już określone i nie powinny być już zmieniane ze względu na szybkość renderowania.

teraz wyobraź sobie górny margines -10 pikseli dla ramki 3. zamiast przesuwać wszystkie poprzednie elementy w górę, aby zebrać trochę miejsca, przeglądarka po prostu przesunie pole 3 w górę, więc jest renderowane na górze (lub pod spodem, w zależności od indeksu Z ) wszelkie poprzednie elementy. nawet jeśli wydajność nie była problemem, przesunięcie wszystkich elementów w górę mogłoby oznaczać przesunięcie ich poza obszar wyświetlania, a zatem bieżąca pozycja przewijania musiałaby zostać zmieniona, aby wszystko było ponownie widoczne.

to samo dotyczy dolnego marginesu dla pola 3, zarówno negatywnego, jak i pozytywnego: zamiast wpływać na już ocenione elementy, określa się tylko nowy „punkt wyjścia” dla kolejnych elementów. w ten sposób ustawienie dodatniego dolnego marginesu spycha w dół następujące elementy; negatywny spowoduje ich wzrost.

schellmax
źródło
NAJLEPSZA odpowiedź. Ta również wyjaśnia „dlaczego”, podczas gdy inne odpowiedzi wyjaśniają tylko „jak”.
Amir Hossein Ahmadi
1
Ta odpowiedź pomogła mi zrozumieć, dlaczego lepiej. Dziękuję @schellmax
iRamesh
3

Ponieważ użyłeś pozycjonowania bezwzględnego i określiłeś górną wartość procentową, tylko margines górny wpłynie na lokalizację twojego obiektu. Jeśli zamiast tego umieścisz go za pomocą bottom: 50%, potrzebujesz margin-bottom -8px, aby go wyśrodkować, a margin-top nie przyniesie żadnego efektu.

Margines wpływa na granice elementu pod względem pozycjonowania go, absolutnie jak w twoim przypadku lub względem sąsiednich elementów. Wyobraź sobie, że margines jest podstawą Twojego elementu, na którym się znajduje. Zwykle mają ten sam rozmiar, ale można je powiększyć lub zmniejszyć na dowolnej lub wszystkich czterech krawędziach.

Twój CSS mówi przeglądarce, aby umieściła górę elementu na marginesie w punkcie 50% w dół strony. Jednak ponieważ wszystkie elementy nie są pojedynczym pikselem, przeglądarka musi wiedzieć, która jego część zajmuje 50% długości strony. Aby wyrównać górę elementu, używa górnego marginesu. Domyślnie jest to zgodne z górną częścią elementu, ale możesz to zmienić za pomocą CSS.

W Twoim przypadku górne 50% spowodowałoby, że górna część elementu zaczynałaby się na środku strony. Stosując ujemny górny margines, przeglądarka używa punktu 8px w elemencie od góry (tj. Linii przechodzącej przez jego środek) jako miejsca do pozycjonowania na 50%.

Jeśli zastosujesz dodatni margines na dole, wydłuża to linię, której przeglądarka używa do umieszczenia dna z dala od samego elementu, tworząc odstęp między nim a dowolnym sąsiednim elementem poniżej lub wpływając na to, gdzie jest on umieszczony bezwzględnie, jeśli pozycjonowanie oparte jest na dół.

Rob Trickey
źródło
+1. To ma sens ... wspaniale byłoby rozszerzyć go o wskazówki wizualne, aby zakończyć wizualizację .
PhD,
3

Zastanawiam się, czy dobrze odpowiedziano na to pytanie: jak działają marginesy css i dlaczego tak się dzieje margin-top: -5; to nie to samo co margin-bottom: 5 ;?

Margines to odległość od otoczenia elementu. margin-top mówi „… odległość od otoczenia mierzona od górnej strony„ pudełka ”elementu, a margin-bottom to odległość od dolnej„ strony ”„ pudełka ”. Następnie margin-top: 5; dotyczy obwodu „górnej strony”, w tym przypadku -5; wszystko, co zbliża się z „boku” z góry, może nachodzić na „bok” elementu o 5 i margin-bottom: 5; oznacza, że ​​odległość pomiędzy dolną stroną elementu a otoczeniem wynosi 5.

Zasadniczo to, ale wpływa na elementy pływające i tym podobne: http://www.w3.org/TR/CSS2/box.html#margin-properties .

http://coding.smashingmagazine.com/2009/07/27/the-definitive-guide-to-using-negative-margins/

Chcę zostać poprawiony.

Może
źródło