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

322

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

Что я ожидал:
То, что я ожидал с полем: 50px 50px 50px 50px;

Что я получаю:
Что я получаю с полем: 50px 50px 50px 50px;

Код:

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

В школах W3 нет объяснения, почему маржа ведет себя так.

jamietelin
источник
4
ты пытался плавать внутренний?
Петух
6
гул .. с float:left;этим работает ... но зачем это нужно. Я не хочу, чтобы это плавало. И почему работает поле слева / справа?
jamietelin
44
Добро пожаловать в увлекательный мир алгоритма коллапса CSS margin!
GordonM
10
W3Schools vs. W3CDocs ... Я думаю, что у нас есть победитель. : D
enderskill
15
jsFiddle из этого, чтобы сохранить следующий парень 25 секунд jsfiddle.net/kLeu9
CodyBugstein

Ответы:

454

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

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

8.3.1 Сокращение полей

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

Смешение вертикальных полей рухнет [...]

Два поля соприкасаются, если и только если:

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

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

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

  • Поля между плавающим блоком и любым другим блоком не разрушаются (даже между плавающим элементом и его дочерними элементами в потоке).
  • Поля элементов, которые устанавливают новые контексты форматирования блока (такие как плавающие элементы и элементы с «переполнением», отличным от «видимого»), не разрушаются вместе со своими дочерними элементами в потоке.
  • Поля встроенных блоков не разрушаются (даже при наличии дочерних элементов).

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

Горизонтальные поля никогда не разрушаются.

BoltClock
источник
2
Этот ответ потрясающий! Просто кое-что добавить. Ваша цитата из w3c говорит об этом, но я понял только сейчас. Так что, чтобы быть понятным другим, вы также можете дать #outer границу.
дричел
Ссылка в Floating, кажется, не работает.
EP
@episanty: Вот что происходит, когда вы ссылаетесь на комментарий. Несвязанными.
BoltClock
Я знаю - просто хотел, чтобы ты знал. Поскольку вы ♦ -включены, я подумал, что вы, возможно, захотите воскресить комментарий или изменить свое сообщение соответствующим образом. Спасибо за хороший ответ, кстати.
EP
92

Попробуйте использовать 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;
}
enderskill
источник
6
Хороший ответ. Было бы лучше, если бы он объяснил, почему это изменение решает проблему.
JohnFx
1
Хорошо, это странно! Почему это работает? Каково логическое объяснение того, почему это не работает так, как можно было бы ожидать. Маржа влево / вправо работает без display:inline-block;. Также при установке используется значение, при display:inline-block;котором вы теряете ширину в 100% на div.
jamietelin
3
переключение на inline-block заставляет браузер переоценивать размер div после его размещения и применения других правил.
Петух
Попробовал это для моей проблемы, сделал эффект лестницы.
Джонни
1
display:inline-blockработал на меня. Огромное спасибо.
Старкин
24

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

Решение 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

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

Это не имеет большого отношения к вопросу, так как это разрыв между братьями и сестрами. Обычно это означает, что есть приставка, 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 ссылок и изображений из-за моей репутации новичка. По крайней мере, вы знаете, откуда возникла проблема, когда в следующий раз увидите нечто подобное.

Цян
источник
14

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

overflow: auto;

к внешнему div.

Brandon
источник
Множество разных решений этой проблемы. Спасибо! Этот ответ в сочетании с ответом @ BoltClock дает хорошую информацию о том, почему это решение работает.
jamietelin
12

Если вы добавляете какие-либо отступы #outer, это работает.

демонстрация

#outer {
    width:500px; 
    height:200px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:block;
    padding-top:1px;
}
bookcasey
источник
11

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

display:inline-block;

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

harriyott
источник
3

Не отвечает на вопрос «почему» (должно быть что-то со складывающимся запасом), но кажется, что самый простой / логичный способ сделать то, что вы пытаетесь сделать, это просто добавить padding-topк внешнему div :

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

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

Дейв
источник
3

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

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

Удачи

Мустафа М Джалал
источник
2

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

viditkothari
источник
2

Используйте padding-top:50pxдля внешнего div. Что-то вроде этого:

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

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

#outer {
    width:500px; 
    height:150px; 
    background:#FFCCCC;
    margin:50px auto 0 auto;
    display:table;}
Ата Иревани
источник
1

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

margin:50px 50px 50px 50px !important;
atgr24869
источник
-1

Просто для быстрого исправления попробуйте обернуть ваши дочерние элементы в такой divэлемент -

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

Край innerdiv не рухнет из-за отступов 1pxмежду ними outerи innerdiv. Таким образом, по логике у вас будет 1pxдополнительное пространство вместе с существующим полем innerdiv.

Митилеш Типкари
источник