Все, что вам нужно знать о полях CSS
Опубликовано: 2022-03-10 Одной из первых вещей, которую большинство из нас усвоили, изучая CSS, были детали различных частей блока в CSS, описанные как модель блока CSS. Одним из элементов блочной модели является поле, прозрачная область вокруг блока, которая будет отталкивать другие элементы от содержимого блока. Свойства margin-top
, margin-right
, margin-bottom
и margin-left
были описаны еще в CSS1 вместе с сокращенным margin
для одновременной установки всех четырех свойств.
Маржа кажется довольно простой вещью, однако в этой статье мы рассмотрим некоторые вещи, которые сбивают людей с толку в отношении использования маржи. В частности, мы рассмотрим, как поля взаимодействуют друг с другом и как на самом деле работает схлопывание полей.
Блочная модель CSS
Как и во всех статьях о частях блочной модели CSS, мы должны определить, что мы подразумеваем под этим, и как модель была прояснена с помощью версий CSS. Блочная модель относится к тому, как различные части блока — содержимое, отступы, границы и поля — располагаются и взаимодействуют друг с другом. В CSS1 блочная модель была детализирована художественной диаграммой ASCII, показанной на изображении ниже.
Четыре свойства поля для каждой стороны блока и сокращенное обозначение margin
были определены в CSS1.
Спецификация CSS2.1 содержит иллюстрацию для демонстрации блочной модели, а также определяет термины, которые мы до сих пор используем для описания различных боксов. Спецификация описывает content box
padding box
border box
и margin box
, каждый из которых определяется краями содержимого, отступами, границей и полем соответственно.
В настоящее время существует спецификация блочной модели уровня 3 в качестве рабочего проекта. Эта спецификация ссылается на CSS2 для определений блочной модели и полей, поэтому это определение CSS2, которое мы будем использовать в большей части этой статьи.
Свертывание поля
Спецификация CSS1, поскольку она определяет поля, также определяет, что вертикальные поля схлопываются . С тех пор это коллапсирующее поведение стало источником разочарования, связанного с маржей. Сворачивание полей имеет смысл, если учесть, что в те первые дни CSS использовался как язык форматирования документации. Сворачивание полей означает, что когда за заголовком с нижним полем следует абзац с верхним полем, у вас не будет большого разрыва между этими элементами.
Когда поля схлопываются, они объединяются, так что пространство между двумя элементами становится больше из двух полей. Меньшее поле по существу заканчивается внутри большего.
Поля схлопываются в следующих случаях:
- Соседние братья и сестры
- Полностью пустые коробки
- Родительский и первый или последний дочерний элемент
Давайте рассмотрим каждый из этих сценариев по очереди, прежде чем рассматривать факторы, которые предотвращают падение маржи в этих сценариях.
Соседние братья и сестры
Мое первоначальное описание схлопывания полей — это демонстрация того, как схлопываются поля между соседними одноуровневыми элементами. За исключением ситуаций, упомянутых ниже, если у вас есть два элемента, отображаемые один за другим в обычном потоке, нижнее поле первого элемента совпадет с верхним полем следующего элемента.
В приведенном ниже примере CodePen есть три элемента div
. Первый имеет верхнее и нижнее поле по 50 пикселей. Второй имеет верхнее и нижнее поле 20px. Третий имеет верхнее и нижнее поле 3em. Поле между первыми двумя элементами составляет 50 пикселей, так как меньшее верхнее поле объединяется с большим нижним полем. Поле между вторыми двумя элементами в 3em, так как 3em больше, чем 20 пикселей внизу второго элемента.
Полностью пустые коробки
Если поле пусто, то его верхнее и нижнее поля могут схлопываться друг с другом. В следующем примере CodePen элемент с классом empty имеет верхнее и нижнее поле по 50 пикселей, однако расстояние между первым и третьим элементами составляет не 100 пикселей, а 50. Это происходит из-за схлопывания двух полей. Добавление чего-либо в это поле (даже заполнения) приведет к тому, что верхнее и нижнее поля будут использоваться, а не свернутся.
Родительский и первый или последний дочерний элемент
Это сценарий коллапса маржи, который чаще всего бросается в глаза людям, поскольку он не кажется особенно интуитивным. В следующем CodePen у меня есть div
с классом-оболочкой, и я выделил этот div
красным outline
, чтобы вы могли видеть, где он находится. Все три дочерних элемента имеют отступ в 50 пикселей. Однако первый и последний элементы находятся на одном уровне с краями обертки; между элементом и оболочкой нет поля в 50 пикселей.
Это связано с тем, что поле дочернего элемента схлопывается с любым полем родителя, таким образом, оказываясь снаружи родителя. Вы можете увидеть это, если проверите первый дочерний элемент с помощью DevTools. Выделенная желтым цветом область — это поле.
Свернуть только поля блока
Последний пример также подчеркивает кое-что о схлопывании полей. В CSS2 для сворачивания указаны только вертикальные поля — это верхнее и нижнее поля элемента, если вы находитесь в режиме горизонтального письма. Таким образом, левое и правое поля выше не схлопываются и не оказываются за пределами оболочки.
Примечание . Стоит помнить, что поля схлопываются только в блочном направлении, например, между абзацами.
Вещи, которые предотвращают обрушение маржи
Поля никогда не схлопываются, если элемент имеет абсолютное позиционирование или плавает. Однако, предполагая, что вы столкнулись с одним из описанных выше мест, где поля рушатся, как вы можете остановить эти крахи?
Первое, что перестает разрушаться, — это ситуации, когда между рассматриваемыми элементами что-то есть.
Например, поле, полностью пустое от содержимого, не свернет свое верхнее и нижнее поле, если у него есть граница или применены отступы. В приведенном ниже примере я добавил отступ в поле на 1 пиксель. Теперь над и под полем есть поле в 50 пикселей.
За этим стоит логика: если блок полностью пуст, без границ или отступов, он практически невидим. Это может быть пустой элемент абзаца, добавленный вашей CMS в разметку. Если бы ваша CMS добавляла избыточные элементы абзаца, вы, вероятно, не хотели бы, чтобы они вызывали большие промежутки между другими абзацами из-за того, что их поля учитываются. Добавьте что-нибудь в коробку, и вы получите эти пробелы.
Аналогичное поведение можно увидеть с полями на первом или последнем дочернем элементе, которые схлопываются через родителя. Если мы добавим границу к родителю, поля дочерних элементов останутся внутри.
Опять же, в поведении есть некоторая логика. Если у вас есть элементы обтекания для семантических целей, которые не отображаются визуально, вы, вероятно, не хотите, чтобы они создавали большие пробелы в отображении. Это имело большой смысл, когда веб был в основном текстовым. Это менее полезно как поведение, когда мы используем элементы для макета дизайна.
Создание контекста форматирования блока
Новый контекст блочного форматирования (BFC) также предотвратит схлопывание полей через содержащий элемент. Если мы снова посмотрим на пример первого и последнего дочерних элементов, в результате чего их поля оказались за пределами обертки, и дадим оболочке display: flow-root
, тем самым создав новый BFC, поля останутся внутри.
Чтобы узнать больше о display: flow-root
, прочитайте мою статью «Понимание макета CSS и контекста форматирования блоков». Изменение значения свойства overflow
на auto
будет иметь тот же эффект, поскольку при этом также создается новый BFC, хотя в некоторых сценариях также могут создаваться полосы прокрутки, которые вам не нужны.
Flex и Grid-контейнеры
Контейнеры Flex и Grid устанавливают контексты форматирования Flex и Grid для своих дочерних элементов, поэтому их поведение отличается от блочного макета. Одно из этих отличий заключается в том, что поля не схлопываются:
«Flex-контейнер устанавливает новый гибкий контекст форматирования для своего содержимого. Это то же самое, что и установка контекста форматирования блока, за исключением того, что вместо блочного макета используется гибкий макет. Например, объекты с плавающей запятой не вторгаются во флекс-контейнер, а поля флекс-контейнера не схлопываются вместе с полями его содержимого».
— Флексбокс Уровень 1
Если мы возьмем приведенный выше пример и превратим оболочку во гибкий контейнер, отображая элементы с помощью flex-direction: column
, вы увидите, что поля теперь содержатся в оболочке. Кроме того, поля между соседними гибкими элементами не схлопываются друг с другом, поэтому мы получаем 100 пикселей между гибкими элементами, всего 50 пикселей сверху и снизу элементов.
Маржинальные стратегии для вашего сайта
Из-за коллапса отступов рекомендуется разработать согласованный способ работы с отступами на вашем сайте. Самое простое, что можно сделать, это определить поля только сверху или снизу элементов. Таким образом, вы не должны слишком часто сталкиваться с проблемами схлопывания полей, поскольку сторона с полем всегда будет примыкать к стороне без поля.
Примечание . У Гарри Робертса есть отличный пост, в котором подробно описаны причины, по которым установка полей только в одном направлении является хорошей идеей, а не только из-за решения проблем с коллапсом полей.
Это решение не решает проблемы, с которыми вы можете столкнуться, когда поля для дочерних элементов рушатся из-за их родителя. Эта конкретная проблема, как правило, менее распространена, и знание того, почему это происходит, может помочь вам найти решение. Идеальным решением для этого является предоставление компонентам, которые требуют его display: flow-root
, в качестве запасного варианта для старых браузеров вы можете использовать overflow
для создания BFC, превратить родителя в flex-контейнер или даже добавить один пиксель заполнения. Не забывайте, что вы можете использовать запросы функций для обнаружения поддержки display: flow-root
, чтобы только старые браузеры получали менее оптимальное исправление.
В большинстве случаев я считаю, что ключевым моментом является знание того, почему маржа падает (или не падает). Затем вы можете выяснить в каждом конкретном случае, как с этим бороться. Что бы вы ни выбрали, обязательно поделитесь этой информацией со своей командой. Довольно часто схлопывание маржи немного загадочно, поэтому причина противодействия этому может быть неочевидной! Комментарий в вашем коде очень поможет — вы даже можете дать ссылку на эту статью и помочь поделиться знаниями о схлопывании полей.
Я подумал, что завершу эту статью несколькими другими сведениями, связанными с маржой.
Процентная маржа
Когда вы используете процент в CSS, это должен быть процент от чего-то. Поля (и отступы), установленные с использованием процентов, всегда будут в процентах от встроенного размера (ширины в режиме горизонтального письма) родителя. Это означает, что при использовании процентов у вас будет отступ одинакового размера по всему элементу.
В приведенном ниже примере CodePen у меня есть обертка шириной 200 пикселей, внутри находится поле с полем 10%, поле составляет 20 пикселей со всех сторон, что составляет 10% от 200.
Поля в мире, связанном с потоком
Мы говорили о вертикальных полях на протяжении всей этой статьи, однако современный CSS имеет тенденцию думать о вещах относительно потока, а не физического способа. Поэтому, когда мы говорим о вертикальных полях, мы действительно говорим о полях в блочном измерении. Эти поля будут верхним и нижним, если мы находимся в режиме горизонтального письма, но будут правым и левым в режиме вертикального письма, написанным слева направо.
После работы с логическими относительными направлениями потока становится легче говорить о начале и конце блока, а не о верхе и низу. Чтобы упростить эту задачу, в CSS введена спецификация логических свойств и значений. Это отображает относительные свойства потока на физические.
Для полей это дает нам следующие сопоставления (если мы работаем на английском или любом другом горизонтальном режиме письма с направлением текста слева направо).
-
margin-top
граница =margin-block-start
-
margin-right
=margin-inline-end
-
margin-bottom
граница =margin-block-end
-
margin-left
=margin-inline-start
У нас также есть два новых сокращения, которые позволяют устанавливать оба блока сразу или оба встроенных.
-
margin-block
-
margin-inline
В следующем примере CodePen я использовал эти относительные ключевые слова потока, а затем изменил режим записи поля, вы можете видеть, как поля следуют направлению текста, а не привязаны к физическому верху, правому, нижнему и левому краю.
Вы можете больше узнать о логических свойствах и значениях на MDN или в моей статье «Понимание логических свойств и значений» здесь, в Smashing Magazine.
Обернуть
Теперь вы знаете большую часть того, что нужно знать о полях! Вкратце:
- Схлопывание маржи — это вещь. Понимание того, почему это происходит и когда это не помогает, поможет вам решить любые проблемы, которые могут возникнуть.
- Установка отступов только в одном направлении решает многие головные боли, связанные с отступами.
- Как и во всем, что касается CSS, делитесь со своей командой решениями, которые вы принимаете, и комментируйте свой код.
- Размышление о блочных и встроенных размерах, а не о физических верхнем, правом, нижнем и левом, поможет вам, поскольку Интернет движется к тому, чтобы быть независимым от режима письма.