Почему этот стиль CSS margin-top не работает?

Я пытаюсь добавить значения маржи на div внутри другого div. Все работает нормально, кроме верхнего значения, кажется, игнорируется. Но почему?

то, что я ожидал:
What I expected with <a href=margin:50px 50px 50px 50px;" src="/images/content/9519841/283af29b538262c3277c0241e54eece9.jpg">

что я получаю:
What I get with margin:50px 50px 50px 50px;

код:

css lang-css prettyprint-override">#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;
}
html lang-html prettyprint-override"><div id="outer">
  <div id="inner">
  	Hello world!
  </div>
</div>

W3Schools не имеют объяснения, почему маржа ведет себя таким образом.

11 ответов


вы на самом деле видите верхний край #inner элемент коллапс в верхний край #outer элемент, оставив только #outer поле нетронутым (хотя и не показано на Ваших изображениях). Верхние края обоих ящиков расположены вплотную друг к другу, поскольку их поля равны.

вот соответствующие моменты из спецификации W3C:

8.3.1 рушится пределах

в CSS, прилегающие поля двух или более коробки (которые могут быть или не быть братьями и сестрами) могут объединяться в единый запас. Поля, которые объединяются таким образом, называются коллапс, и результирующая объединенная маржа называется рухнул маржа.

прилегающие вертикальные поля рушатся [...]

два поля смежно, если и только если:

  • оба принадлежат к блокам уровня в-потока, которые участвуйте в том же контексте форматирования блоков
  • нет линейных ящиков, нет зазора, нет прокладки и нет границы отделить их
  • оба принадлежат к вертикально-смежных краев коробки, т. е. образуют одну из следующих пар:
    • верхний край коробки и верхний край ее первого в потоке ребенка

причина, по которой выполнение любого из следующих действий предотвращает маржу от рушится:

потому что:

  • поля между плавающей коробкой и любой другой коробкой не сворачиваются (даже между поплавком и его потоковыми детьми).
  • поля элементов, которые устанавливают новые контексты форматирования блоков (например, поплавки и элементы с "переполнением", кроме "видимого"), не сворачиваются с их дочерними элементами в потоке.
  • поля встроенных блоков не сворачиваются (даже с их дочерними элементами в потоке).

левое и правое поля ведут себя так, как вы ожидаете, потому что:

горизонтальные поля никогда не рухнет.


попробуйте использовать display: inline-block; на внутреннем 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;
}

то, что @BoltClock упомянуто, довольно солидно. И вот я просто хочу добавить еще несколько решений для этой проблемы. проверьте это w3c_collapsing margin. Зеленые части-это потенциальная мысль о том, как эту проблему можно решить.

Решение 1

поля между плавающей коробкой и любой другой коробкой не сворачиваются (даже между поплавком и его потоковыми детьми).

это означает, что я могу добавить float:left или #outer или #inner demo1.

также обратите внимание, что float аннулирует auto в поле.

решение 2

поля элементов, которые устанавливают новые контексты форматирования блоков (например, поплавки и элементы с "переполнением", кроме "видимого"), не сворачиваются с их дочерними элементами в потоке.

кроме visible, скажем overflow: hidden на #outer. И этот путь кажется довольно простым и приличным. Мне это нравится.

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

решение 3

поля абсолютно расположенных ящиков не сворачиваются (даже с их детьми в потоке).

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

или

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

эти два метода нарушат нормальный поток div

решение 4

поля инлайн-блок-боксах не рухнет (не даже с их детьми в потоке).

такой же, как @enderskill

решение 5

нижний край элемента уровня блока в потоке всегда разрушается с верхним краем его следующего брата уровня блока в потоке, если у этого брата нет зазора.

это не имеет большого отношения к вопросу, так как это рушится разница между братьями и сестрами. это обычно означает, если top-box имеет margin-bottom: 30px и у братской коробки есть margin-top: 10px. Общая разница между ними 30px вместо 40px.

решение 6

верхний край элемента блока в потоке сворачивается с его первым в потоке на уровне блока верхнего края ребенка, если элемент не имеет верхней границы, без верхнего заполнения, и ребенок не имеет зазора.

это очень интересно, и я могу просто добавить одну верхнюю границу линия

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

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

}

И <div> блок-уровня по умолчанию, поэтому вам не нужно объявлять это намеренно. Извините, что не могу опубликовать более 2 ссылок и изображений из-за моей начинающей репутации. По крайней мере, вы знаете, где проблема возникает в следующий раз, когда вы видите что-то подобное.


Не уверен, почему то, что у вас не работает, но вы можете добавить

overflow: auto;

к внешнему div.


Если вы добавите любое дополнение к #outer, он работает.

демо

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

не совсем уверен, почему, но изменение внутреннего CSS на

display:inline-block;

Кажется, работает;


не отвечает на "почему" (должно быть что-то w/ collapsing margin), но кажется, что самый простой/самый логичный способ сделать то, что вы пытаетесь сделать, - это просто добавить padding-top к внешнему div:

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

незначительное примечание - не должно быть необходимости устанавливать div в display:block; если в вашем коде нет чего-то еще, что говорит ему не быть блоком.


попробуйте это:

#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/

удачи


Я думаю, задание позиция свойства #inner div to относительные может также помочь достигнуть влияния. Но в любом случае я попробовал оригинальный код, вставленный в вопрос на IE9 и последний Google Chrome, и они уже дают желаемый эффект без каких-либо изменений.


использовать padding-top:50pxдля наружного div. Что-то вроде этого:--4-->

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

Примечание: заполнение увеличит размер вашего div. В этом случае, если размер вашего div важен, я имею в виду, если он должен иметь определенную высоту. уменьшить высоту в 50px.:

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

вы пробовали !важно, прежде всего, это заставит все:

margin:50px 50px 50px 50px !important;