Схлопывание margin
Иногда поведение вертикальных внешних отступов элемента margin-top и margin-bottom может вызвать недоумение у начинающего верстальщика. Возьмем, к примеру, какой-нибудь типичный фрагмент кода:
<div class="parent"> <h1>Заголовок </h1> <p>Абзац</p> <p>Абзац</p> <ul> <li>Первый элемент списка</li> <li>.........................</li> <li>Последний элемент списка</li> </ul> <p>Абзац</p> </div>
.parent { margin: 0 auto; width: 500px; } h1 { margin: 15px 5px; } ul { margin: 5px; } li { margin:5px 0; } p { margin:5px; }
На первый взгляд может показаться, что все должно выглядеть так, как на рисунке ниже (для удобства блоки раскрашены):
На практике же все получается немного по-другому. Смотрим демо-пример.
Чтобы не мерить линейкой экран, все размеры отступов приведены на рисунке:
Откуда взялся у родительского элемента ненулевой верхний отступ? И вообще отступы у элементов сильно отличаются от ожидаемых. Что же это такое и почему так получается?
Почему отступы разные?
На самом деле никакой мистики нет — отступы отрисовываются именно такими, какими их задали в CSS. Просто произошло схлопывание margin — соприкасающиеся отступы как бы проникают друг в друга.
Заметка. Согласно спецификации CSS2.1 горизонтальные margin никогда не схлопываются. Схлопывание влияет только на вертикальные margin!
Как проявляется схлопывание вертикальных margin
Схлопывание проявляется двумя эффектами:
-
Схлопываются соседние отступы смежных элементов.
Вот так они накладываютсяВертикальный отступ между элементами равен не сумме двух отступов соседних элементов, а большему из этих отступов.
-
Схлопываются вертикальные внешние отступы родителя и потомка. Результирующий отступ равен большему из схлопываюшихся margin. Это приводит к тому, что если у дочернего элемента margin больше чем у родителя, то он как бы выталкивает родителя:
Margin дочернего элемента увеличивает отступ родителяВ примере приведенном выше у родительского элемента был верхний маржин 5px, но он схлопнулся с верхним маржином 10px дочернего элемента. В результате получили у верхний результирующий отступ 10px — родитель «провалился» на 5px вниз. Обрати внимание! Отступа между родителем и потомком в такой ситуации не будет.
Схлопываются как верхний отступ родителя с верхним отступом первого дочернего элемента, так и нижний отступ родителя с нижним отступом последнего дочернего элемента.
Если один из margin отрицательный, а другой положительный, результирующий отступ будет равен их сумме.
Где это можно использовать?
Схлопывание вертикальных внешних отступов удобно при разметке контента. Например, для абзацев задаем такое правило:
p { margin:10px 0; }
Если бы схлопывания не существовало, то отступы между абзацами были бы по 20px, а отступ перед первым абзацем и после последнего — только 10 (т.е. в два раза меньше)! Чтобы отступы были равномерными, пришлось бы дополнительно повозиться.
А так все в порядке, соседние отступы схлопнутся — получаем предсказуемый одинаковый отступ по 10px.
В каких случаях схлопывания не будет?
Схлопывание вертикальных отступов не происходит между:
- родительским элементом и дочерним элементом, если у родительского элемента с этой стороны есть внутренний отступ (padding) или граница (border);
- плавающим блоком и любыми другими блоками (в том числе и дочерними блоками);
- абсолютно спозиционированным блоком и любыми другими блоками (в том числе и дочерними блоками)
- строчным блоком и любыми другими блоками (в том числе и дочерними блоками);
- элементом устанавливающим новый контекст форматирования (например, плавающим блоком или блоком с overflow отличным от visible) и его дочерними блоками;
- корневым элементом и его дочерними блоками.
Как поступать, если схлопывание отступов не нужно?
Между смежными элементами схлопывание отступов убирать, как правило, не требуется (тем не менее такая возможность есть). А вот ситуация, когда схлопываются вертикальные отступы дочернего и родительского элемента, чаще всего нежелательна.
Различные варианты убрать схлопывание смотри в статье Обходим схлопывание margin.
Материалы:
- W3C:: Box model :: Collapsing margins
- UEric A. Meyer :: Uncollapsing Margins