Warum funktioniert dieser CSS-Rand-Top-Stil nicht?

321

Ich versuche, Randwerte für ein Div in einem anderen Div hinzuzufügen. Alles funktioniert gut, bis auf den Spitzenwert, es scheint ignoriert zu werden. Aber warum?

Was ich erwartet habe:
Was ich mit Rand erwartet habe: 50px 50px 50px 50px;

Was ich bekomme:
Was ich mit Rand bekomme: 50px 50px 50px 50px;

Code:

#outer {
    	width: 500px; 
    	height: 200px; 
    	background: #FFCCCC;
    	margin: 50px auto 0 auto;
    	display: block;
}
#inner {
    	background: #FFCC33;
    	margin: 50px 50px 50px 50px;
    	padding: 10px;
    	display: block;
}
<div id="outer">
  <div id="inner">
  	Hello world!
  </div>
</div>

W3Schools haben keine Erklärung dafür, warum sich Margin so verhält.

Jamietelin
quelle
4
Hast du versucht, den inneren zu schweben?
Hahn
6
Brummen .. Damit float:left;funktioniert ... aber warum wird das gebraucht? Ich möchte nicht, dass es schwimmt. Und warum funktioniert der Spielraum für links / rechts?
Jamietelin
44
Willkommen in der unterhaltsamen Welt des CSS-Margin-Collapse-Algorithmus!
GordonM
10
W3Schools vs. W3CDocs ... Ich denke, wir haben einen Gewinner. : D
Enderkill
15
jsFiddle davon, um den nächsten Kerl 25 Sekunden zu retten jsfiddle.net/kLeu9
CodyBugstein

Antworten:

453

Sie sehen tatsächlich den oberen Rand des #innerElements Zusammenbruch in den oberen Rand des #outerElements, nur die #outerAbgangsmarge intakt (wenn auch nicht in Ihren Bildern gezeigt). Die Oberkanten beider Boxen sind bündig aneinander, da ihre Ränder gleich sind.

Hier sind die relevanten Punkte aus der W3C-Spezifikation:

8.3.1 Reduzieren von Rändern

In CSS können die angrenzenden Ränder von zwei oder mehr Feldern (die möglicherweise Geschwister sind oder nicht) zu einem einzigen Rand kombiniert werden. Ränder, die auf diese Weise kombiniert werden, werden als kollabiert bezeichnet , und der resultierende kombinierte Rand wird als reduzierter Rand bezeichnet .

Angrenzende vertikale Ränder kollabieren [...]

Zwei Ränder grenzen genau dann aneinander, wenn:

  • Beide gehören zu In-Flow-Boxen auf Blockebene, die am gleichen Blockformatierungskontext teilnehmen
  • Keine Linienkästen, kein Abstand, keine Polsterung und kein Rand trennen sie
  • beide gehören zu vertikal benachbarten Kastenkanten, dh bilden eines der folgenden Paare:
    • oberer Rand einer Box und oberer Rand ihres ersten in-flow-Kindes

Sie können eine der folgenden Aktionen ausführen, um zu verhindern, dass der Rand zusammenbricht:

Der Grund, warum die oben genannten Optionen verhindern, dass der Rand zusammenbricht, ist folgender:

  • Die Ränder zwischen einer schwebenden Box und einer anderen Box fallen nicht zusammen (nicht einmal zwischen einem Float und seinen untergeordneten Elementen).
  • Ränder von Elementen, die neue Blockformatierungskontexte einrichten (z. B. Floats und Elemente mit einem anderen als "sichtbaren" Überlauf), werden nicht mit ihren untergeordneten Elementen zusammengeführt.
  • Die Ränder von Inline-Block-Boxen fallen nicht zusammen (auch nicht bei ihren In-Flow-Kindern).

Der linke und der rechte Rand verhalten sich wie erwartet, weil:

Horizontale Ränder fallen niemals zusammen.

BoltClock
quelle
12
Anscheinend sind Sie nicht der einzige, der denkt, dass es dumm ist ...
BoltClock
2
Diese Antwort rockt! Nur etwas hinzuzufügen. Ihr Zitat von w3c sagt es, aber ich habe es erst jetzt erkannt. Um anderen klar zu sein, können Sie #outer auch eine Grenze geben.
Driechel
Die Verbindung in Floating scheint unterbrochen zu sein.
EP
@episanty: Das passiert, wenn du auf einen Kommentar verlinkst. Nicht verbunden.
BoltClock
Ich weiß - wollte dich nur wissen lassen. Da Sie ♦ -aktiviert sind, dachte ich, Sie möchten den Kommentar möglicherweise wiederbeleben - oder Ihren Beitrag entsprechend ändern. Danke übrigens für die gute Antwort.
EP
92

Versuchen Sie es mit display: inline-block;dem inneren Div.

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:block;
}
#inner {
    background:#FFCC33;
    margin:50px 50px 50px 50px;
    padding:10px;
    display:inline-block;
}
enderskill
quelle
6
Gute Antwort. Wäre besser, wenn erklärt würde, warum diese Änderung das Problem behebt.
JohnFx
1
Ok, das ist verrückt! Warum funktioniert das? Was ist die logische Erklärung dafür, warum es nicht so funktioniert, wie man es erwarten würde. Rand links / rechts funktioniert ohne display:inline-block;. Ebenfalls zurückgesetzt, wenn Sie verwenden, display:inline-block;ist, dass Sie die Breite von 100% auf dem div verlieren.
Jamietelin
3
Durch das Umschalten auf Inline-Block wird der Browser gezwungen, die Größe des Div neu zu bewerten, nachdem es platziert und andere Regeln angewendet wurden.
Hahn
Versuchte es für mein Problem, machte einen Treppeneffekt.
Jonny
1
display:inline-blockarbeitete für mich. Ich danke dir sehr.
starkeen
24

Was @BoltClock erwähnt hat, ist ziemlich solide. Und hier möchte ich nur einige weitere Lösungen für dieses Problem hinzufügen. Überprüfen Sie diesen w3c_collapsing-Rand . Die grünen Teile sind der mögliche Gedanke, wie dieses Problem gelöst werden kann.

Lösung 1

Die Ränder zwischen einer schwebenden Box und einer anderen Box fallen nicht zusammen (nicht einmal zwischen einem Float und seinen untergeordneten Elementen).

das heißt, ich kann float:leftentweder #outeroder #inner demo1 hinzufügen .

Beachten Sie auch, dass floatdies die autoIn-Marge ungültig machen würde .

Lösung 2

Ränder von Elementen, die neue Blockformatierungskontexte einrichten (z. B. Floats und Elemente mit einem anderen als "sichtbaren" Überlauf), werden nicht mit ihren untergeordneten Elementen zusammengeführt.

ausgenommen visible, Put - Lassen Sie uns overflow: hiddenin #outer. Und dieser Weg scheint ziemlich einfach und anständig. Ich mag das.

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    overflow: hidden;
}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;
}

Lösung 3

Die Ränder absolut positionierter Kisten kollabieren nicht (auch nicht bei ihren unterströmten Kindern).

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    position: absolute; 
}
#inner{
    background: #FFCC33;
    height: 50px;
    margin: 50px;
}

oder

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    position: relative; 
}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;
    position: absolute;
}

Diese beiden Methoden unterbrechen den normalen Fluss von div

Lösung 4

Die Ränder von Inline-Block-Boxen fallen nicht zusammen (auch nicht bei ihren In-Flow-Kindern).

ist das gleiche wie @enderskill

Lösung 5

Der untere Rand eines In-Flow-Block-Level-Elements kollabiert immer mit dem oberen Rand seines nächsten In-Flow-Block-Level-Geschwisters, es sei denn, dieses Geschwister hat Freiraum.

Dies hat nicht viel mit der Frage zu tun, da es sich um den kollabierenden Spielraum zwischen Geschwistern handelt. es bedeutet im Allgemeinen, wenn eine Top-Box hat margin-bottom: 30pxund eine Geschwister-Box hat margin-top: 10px. Die Gesamtspanne zwischen ihnen ist 30pxstatt 40px.

Lösung 6

Der obere Rand eines In-Flow-Blockelements wird mit dem oberen Rand des ersten untergeordneten In-Flow-Blockelements reduziert, wenn das Element keinen oberen Rand, keine obere Polsterung und das Kind keinen Abstand hat.

Das ist sehr interessant und ich kann nur eine obere Grenzlinie hinzufügen

#outer{
    width: 500px;
    height: 200px;
    background: #FFCCCC;
    margin: 50px auto;
    border-top: 1px solid red;

}
#inner {
    background: #FFCC33;
    height: 50px;
    margin: 50px;

}

Und <div>ist ebenfalls standardmäßig auf Blockebene, sodass Sie es nicht absichtlich deklarieren müssen. Es tut mir leid, dass ich aufgrund meines unerfahrenen Rufs nicht mehr als 2 Links und Bilder posten kann. Zumindest wissen Sie, woher das Problem kommt, wenn Sie das nächste Mal etwas Ähnliches sehen.

Qiang
quelle
14

Nicht sicher, warum das, was Sie haben, nicht funktioniert, aber Sie können hinzufügen

overflow: auto;

zum äußeren div.

Brandon
quelle
Viele verschiedene Lösungen für dieses Problem. Vielen Dank! Diese Antwort in Kombination mit der Antwort von @ BoltClock liefert gute Informationen darüber, warum diese Lösung funktioniert.
Jamietelin
12

Wenn Sie eine Polsterung hinzufügen #outer, funktioniert dies.

Demo

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:block;
    padding-top:1px;
}
Bücherregal
quelle
11

Ich weiß nicht genau warum, aber ich ändere das innere CSS auf

display:inline-block;

scheint zu funktionieren;

harriyott
quelle
3

Beantwortet nicht das "Warum" (muss etwas mit zusammenbrechendem Rand sein), aber es scheint der einfachste / logischste Weg zu sein, das zu tun, was Sie versuchen, wäre, einfach zum äußeren Div hinzuzufügenpadding-top :

http://jsfiddle.net/hpU5d/1/

Kleinere Anmerkung - es sollte nicht notwendig sein, ein div auf zu setzen, es display:block;sei denn, Ihr Code enthält etwas anderes, das besagt, dass es nicht blockiert werden soll.

Dave
quelle
3

Versuche dies:

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:table;
}
#inner {
    background:#FFCC33;
    margin:50px 50px 50px 50px;
    padding:10px;
    display:block;
}​

http://jsfiddle.net/7AXTf/

Viel Glück

Mustafa M Jalal
quelle
2

Ich denke, das Setzen der Positionseigenschaft des #inner div auf relative kann ebenfalls dazu beitragen, den Effekt zu erzielen. Trotzdem habe ich den Originalcode ausprobiert, der in der Frage zu IE9 und dem neuesten Google Chrome eingefügt wurde, und sie bieten bereits den gewünschten Effekt ohne Änderungen.

viditkothari
quelle
2

Verwenden Sie padding-top:50pxfür äußere div. Etwas wie das:

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:table;}

Hinweis: Durch Auffüllen wird die Größe Ihres Div erhöht. In diesem Fall, wenn die Größe Ihres Div wichtig ist, meine ich, wenn es eine bestimmte Höhe haben muss. Verringern Sie die Höhe um 50px.:

#outer {
    width:500px; 
    height:150px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:table;}
Ata Iravani
quelle
1

Haben Sie es versucht! Wichtig vor allem, es wird alles erzwingen:

margin:50px 50px 50px 50px !important;
atgr24869
quelle
-1

Versuchen Sie für eine schnelle Lösung, Ihre untergeordneten Elemente in ein divElement wie dieses zu verpacken -

<div id="outer">
   <div class="divadjust" style="padding-top: 1px">
      <div id="inner">
         Hello world!
      </div>
   </div>
</div>

Der Rand von innerdiv wird aufgrund des Auffüllens von 1pxdazwischen outerund innerdiv nicht zusammenbrechen. Logischerweise haben Sie also 1pxzusätzlichen Platz zusammen mit dem vorhandenen innerDiv- Rand .

Mithilesh Tipkari
quelle