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

Я пытаюсь добавить значения полей на 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 нет объяснения, почему маржа ведет себя так.

14 ответов

Решение

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

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

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

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

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

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

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

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

  • Плавающий любой из ваших div элементы
  • Делая любой из ваших div элементы встроенных блоков
  • настройка overflow из #outer в auto (или любое значение, кроме visible)

Это потому что:

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

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

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

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

Решение 1

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

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

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

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

overflow: auto;

к внешнему div.

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

display:inline-block;

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

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

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

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

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

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

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

Создать новый контекст форматирования блока

Вы можете использовать display: flow-root на родительском элементе, чтобы предотвратить сворачивание поля через содержащий элемент, когда он создает новый контекст форматирования блока.

Изменение значения свойства overflow на auto или использование flexbox будет иметь тот же эффект.

https://codepen.io/rachelandrew/pen/VJXjEp

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

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

Удачи

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

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

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

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

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

Если у вас есть проблема с коллапсом полей, то для ее решения вы можете добавитьdisplay: flow-root;в родительский контейнер.

Кроме того, если margin-top игнорируется, попробуйте margin-top с отрицательным значением, например:margin-top: -2px;

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

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

Маржа inner div не рухнет из-за заполнения 1px между outer а также innerdiv. Так что по логике у вас будет1px дополнительное пространство вместе с существующим запасом inner div.

Другие вопросы по тегам