Давайте точно рассмотрим, каковы последствия сокращения полей и как они повлияют на элементы на странице.
Спецификация W3C определяет складывающиеся поля следующим образом:
«В данной спецификации выражение сужающиеся поля означает, что смежные поля (без непустого содержимого, отступов или границ или разделения, разделяющего их) двух или более блоков (которые могут быть рядом друг с другом или вложенными) объединяются в форму единственное поле ».
Проще говоря, это определение означает, что когда соприкасаются вертикальные поля двух элементов, будет учитываться только поле элемента с наибольшим значением поля, а поле элемента с меньшим значением поля будет свернуто до нуля. В случае, когда один элемент имеет отрицательное поле, значения полей складываются вместе, чтобы определить окончательное значение. Если оба значения отрицательны, используется большее отрицательное значение. Это определение применяется к смежным элементам и вложенным элементам.
Существуют другие ситуации, когда элементы не имеют свернутых полей:
- плавающие элементы
- абсолютно позиционированные элементы
- встроенные блочные элементы
- элементы с переполнением, установленным на что-либо, кроме видимого (они не сжимают поля со своими потомками)
- очищенные элементы (они не сворачивают свои верхние поля с нижним полем родительского блока.)
- корневой элемент
Это сложная концепция, поэтому давайте рассмотрим несколько примеров.
Сокращение полей между соседними элементами
Поля разрушаются между соседними элементами. Проще говоря, это означает, что для смежных вертикальных элементов уровня блока в обычном потоке документов будет учитываться только поле элемента с наибольшим значением поля, в то время как поле элемента с меньшим значением поля будет свернуто до нуль. Например, если один элемент имеет нижнее поле 25px
а элемент, расположенный непосредственно под ним, имеет верхнее поле 20px
, будет применено только нижнее поле 25px, и элементы останутся на расстоянии 25px
друг от друга. Они не будут на расстоянии 45px
(25 + 20) друг от друга, как и следовало ожидать.
Такое поведение лучше всего продемонстрировать на коротком примере. Рассмотрим следующий код:
h1 { margin: 0 0 25px 0; background: #cfc; } p { margin: 20px 0 0 0; background: #cf9; }
Как видно из рисунка 1, зазор между элементами составляет всего 25 25px
, а меньший запас уменьшился до нуля. Если бы в приведенном выше примере элементы имели одинаковые поля (скажем, по 20 пикселей каждый), расстояние между ними составляло бы только 20 пикселей.
Существует одна ситуация, которая приведет к небольшому отклонению от поведения коллапсирующих полей: если один из элементов имеет отрицательное верхнее или нижнее поле, положительное и отрицательное поля будут складываться вместе для достижения окончательного, истинного поля. Вот пример таблицы стилей, которая демонстрирует концепцию:
h1 { margin: 0 0 25px 0; background: #cfc; } p { margin: -20px 0 0 0; background: #cf9; }
Нижнее поле элемента h1 является положительным числом ( 25px
), а верхнее поле элемента p — отрицательным числом (-20px). В этой ситуации два числа складываются вместе для расчета окончательного поля: 25px
+ (- 20px
) = 5px
.
Если результатом этого вычисления является отрицательное число, это значение будет иметь эффект одного элемента, перекрывающего другой. Можно сказать, что отрицательная маржа тянет элемент в направлении, противоположном положению положительной маржи. См. Поле для более подробной информации об отрицательных наценках.
Сокращение полей между родительским и дочерним элементами
До сих пор мы рассматривали только эффект свертывания смежных элементов, но тот же процесс справедлив для родителей и детей, чьи поля соприкасаются. Под «прикосновением» мы понимаем места, в которых между соседними полями не существует отступов, границ или содержимого. В следующем примере родительский элемент имеет дочерний элемент, для которого установлено верхнее поле:
h1 { margin: 0; background: #cff; } div { margin: 40px 0 25px 0; background: #cfc; } p { margin: 20px 0 0 0; background: #cf9; }
В приведенной выше таблице стилей видно, что для элемента p
объявлено значение верхнего поля, а в приведенном ниже фрагменте кода видно, что элемент p
является дочерним элементом элемента div:
<h1> Заголовок содержимого </ h1> <DIV> <p> Содержание абзаца </ p> </ DIV>
Результат этого кода показан на рисунке 2.
Вы, возможно, ожидали, что абзац будет расположен в 60px
от заголовка, так как элемент div имеет margin-top
40px
а на элементе p
есть еще 20px
margin-top
. Вы также можете ожидать, что 20px
цвета фона элемента div будет отображаться над абзацем. Этого не происходит, потому что, как вы можете видеть на рисунке 2, поля сжимаются вместе, образуя одно поле. Применяется только самый большой запас (как в случае с соседними блоками), как мы уже видели.
Фактически, мы получили бы тот же результат, если бы у нашего элемента div не было верхнего поля, а у элемента p — 40px
margin-top
. 40px
margin-top
40px
на элементе p фактически становится верхним полем элемента div и толкает элемент div вниз на страницу на 40px
, оставляя элемент p
плотно вложенным вверху. На элементе div над абзацем фон не будет виден.
Для того чтобы отображались верхние поля обоих элементов и чтобы фон элемента div отображался над элементом p
, должна быть граница или отступы, которые остановят сужение полей. Если мы просто добавим верхнюю границу к элементу div, мы сможем добиться эффекта, который изначально искали:
h1 { margin: 0; background: #cff; } div { margin: 40px 0 25px 0; background: #cfc; border-top: 1px solid #000; } p { margin: 20px 0 0 0; background: #cf9; }
На рисунке 3 мы можем видеть, что элемент div все еще 40px
расстоянии 40px
от заголовка, но абзац был 40px
еще на 20px
вниз по странице, открывая, таким образом, 20px
фона элемента div (благодаря наличию границы) ,
Если бы мы не хотели, чтобы в дизайне отображалась видимая верхняя граница, верхний отступ 1px
на элементе div достиг бы того же эффекта. Обратите внимание, что граница или отступ должны быть применены к родительскому элементу div, потому что граница в абзаце не помешает полям сворачиваться, поскольку поле абзаца находится за пределами границы.
Приведенный выше пример касается одного родителя и одного дочернего элемента, которые имеют соприкасающиеся поля, но тот же подход будет применяться, если есть несколько дочерних элементов (то есть вложенных элементов), у которых все имеют смежные вертикальные поля: это все равно будет означать, что все поля свернуть в одно поле. Хотя в приведенных выше примерах указаны верхние поля, тот же эффект имеет место для нижних полей, как можно видеть ниже.
В следующем надуманном примере мы вложили четыре элемента div, к каждому из которых применено поле 10px
. Каждый элемент div имеет свой цвет фона, поэтому эффекты свертывания полей будут четко видны:
.box { margin: 10px; } .a { background: #777; } .b { background: #999; } .c { background: #bbb; } .d { background: #ddd; } .e { background: #fff; }
Результат вышеупомянутого CSS показан на рисунке 4.
Как вы можете видеть в этом примере, эффект нашего CSS довольно драматичен: все вертикальные поля свернулись и образовали единое поле размером в 10 10px
. В отличие от примера с горизонтальным полем, где все поля были видны, вертикальные поля вообще не отображают такие цвета благодаря цвету фона, который был применен к каждому элементу. Весь блок будет расположен в 10px
от других элементов потока на странице, но каждый вложенный блок сворачивает свои поля в одно поле.
Как обсуждалось ранее, самый простой способ предотвратить сворачивание полей — это добавить отступы или границы для каждого элемента. Если бы мы хотели, чтобы в каждом элементе были поля в 10px
мы могли бы просто использовать маржу в 9px
и отступы в 1px
чтобы получить 9px
результат:
.box { margin: 9px; padding: 1px; }
Результат этого небольшого изменения «раскладит» вертикальные поля, как вы можете видеть на рисунке 5.
Опять же, важно учитывать эффекты, которые макет в Internet Explorer будет иметь в приведенных выше демонстрациях. Если элементы в первом примере (рисунок 4) имеют макет в IE, результат будет в точности таким, как показано на рисунке 5. Также стоит отметить, что в браузерах, отличных от IE, тот же эффект будет иметь место, если будет добавлено свойство overflow со значением, отличным от видимого.
Завершение
Несмотря на то, что поведение сужения полей на первый взгляд немного неинтуитивно, оно облегчает жизнь в случае нескольких вложенных элементов, где поведение часто желательно. Как показано выше, доступны простые методы, помогающие остановить коллапс при необходимости.