Все, что вам нужно знать о полях CSS
Свойства margin-top, margin-right, margin-bottom и margin-left были описаны еще в первой версии CSS вместе с сокращенной формой margin для установки сразу всех четырех свойств. Но не все так просто с использованием полей в CSS.
Блочная модель CSS
Схема построения блочной модели CSS
В CSS1 были определены четыре свойства поля для каждой стороны и сокращенная форма записи margin.
Спецификация CSS2.1 определяет термины, которые мы используем для описания различных блоков. Эта спецификация описывает content box, padding box, border box, и margin box. Каждый из этих блоков определяется краями содержимого, отступом, границе и полем.
Определение блочной модели в CSS2
Сейчас в качестве проекта существует третья спецификация блочной модели. Эта спецификация ссылается на CSS2, поэтому ее мы и будем использовать.
Сворачивание полей
В CSS1 также определялось сворачивание вертикальных полей. Но оно стало причиной многих проблем. При сворачивании полей двух элементов расстояние между ними приравнивается к размеру поля большего из них. Меньшее поглощается большим.
Поля сворачиваются при использовании следующих элементов:
Смежные элементы одного уровня
В приведенном ниже примере есть три элемента div. Первый имеет верхнее и нижнее поле в 50 пикселей, второй — 20 пикселей, третий — в 3em. Поле между первыми двумя элементами равно 50 пикселей, так как меньшее значение margin-top объединяется с большим нижним.
Поле между вторым и третьим блоком будет иметь величину в 3em. Потому что 3em больше, чем 20 пикселей.
Пустые блоки
Если блок пуст, то его верхнее и нижнее поле сворачиваются. В следующем примере элемент с классом empty имеет верхнее и нижнее поле в 50 пикселей. Но пространство между первым и третьим элементами составляет не 100 пикселей, а 50. Это происходит из-за сужения двух полей. Добавление к этому блоку отступа приведет к отображению верхнего и нижнего полей.
Родительский и первый или последний дочерний элемент
В следующем примере для div с классом wrapper задана красная граница. Три его дочерних div имеют отступ 50 пикселей. Но первый и последний элементы находятся на одном уровне с краями родительского контейнера. Поэтому между ними нет поля в 50 пикселей.
Поле дочернего элемента сворачивается с любым полем родительского контейнера. В результате чего он оказывается снаружи родительского элемента. Чтобы проследить это, просмотрите первый дочерний элемент с помощью инструментов разработчика в браузере. Выделенная желтая область — это поле.
Инструменты разработчика помогают увидеть, где заканчивается поле
Сворачиваются только вертикальные поля
В CSS2 сворачиваются только верхние и нижние поля элемента. Таким образом, левые и правые поля не сворачиваются и не оказываются вне оболочки.
Как предотвратить сворачивание полей
Поля не сворачиваются, если элемент имеет абсолютное позиционирование или является плавающим. Но как предотвратить сворачивание полей в описанных выше случаях?
Сворачивание не происходит, если между блоками задано еще одно пространство. Например, верхнее и нижнее поля пустого блока не свернутся, если у блока есть граница или отступ.
В приведенном ниже примере я добавила для поля отступ в 1px. Теперь у нас есть поле в 50 пикселей сверху и снизу.
Если пустой блок не имеет границы или отступов, он практически невидим. Это может быть абзац, добавленный в разметку CMS. Если CMS автоматически добавляет абзацы, не нужно, чтобы они создавали большие промежутки между остальными абзацами из-за соблюдения их полей. Добавьте содержимое в блок, и вы получите эти промежутки.
Подобное поведение наблюдается у полей первого или последнего дочернего элемента, которые сворачиваются с полями родительского. Если мы добавим границу к родительскому контейнеру, поля дочерних элементов останутся внутри.
Создание контекста блочного форматирования
Контекст блочного форматирования (BFC) предотвращает сворачивание полей элемента. Если в примере с первым и последним дочерним элементом, поля которых заканчиваются за пределами оболочки, установить для контейнера display: flow-root, поля останутся внутри. С помощью этого значения мы создали новый BFC.
Изменение значения свойства overflow на auto даст тот же эффект. Так как это тоже создаст новый BFC.
Flex и Grid-контейнеры
Flex и Grid-контейнеры устанавливают BFC для своих дочерних элементов. Поэтому они по-другому задают поведение блочного макета и поля не сворачиваются.
Если в приведенном выше примере преобразовать контейнер во Flex, отображающий элементы с помощью flex-direction: column, то поля будут размещаться внутри оболочки. При этом поля между смежными Flex-элементами не сворачиваются друг с другом. Поэтому мы получим расстояние в 100 пикселей между ними.
Организация полей
Последовательная обработка полей поможет избавиться от сворачивания. Для этого нужно определить поля только сверху или только снизу элементов. Благодаря этому сторона с полем всегда будет соседствовать со стороной без поля.
Идеальным решением проблемы является указание элементам display: flow-root. В качестве запасного варианта для устаревших браузеров можно использовать overflow для создания BFC, преобразование родительского элемента во Flex-контейнер или добавление отступа величиной в один пиксель. Не забывайте, что вы можете использовать запросы функций для определения поддержки display: flow-root, чтобы менее оптимальное решение предоставлялось только для устаревших браузеров.
Поля в процентах
Поля и отступы, установленные в процентах, всегда будут высчитываться в долях от размера родительского элемента. Поэтому вокруг элемента будет отступ одинакового размера.
В приведенном ниже примере внутри контейнера шириной в 200 пикселей определен блок с полем 10%. То есть, 20 пикселей.
Поля, связанные с потоком
Когда мы работаем с логическими, связанными с потоком направлениями, легче говорить о начале и конце блока, а не о верхнем и нижнем крае. Чтобы упростить это, CSS ввел спецификацию «Логические свойства и значения». Она сопоставляет свойства, связанные с потоком, и физические свойства.
Для полей это дает следующие соответствия:
Также появилось два новых сокращения, которые позволяют устанавливать сразу все свойства блочными или встроенными.
В следующем примере используются эти две сокращенные формы. После изменения направления текста в блоке поля следуют за ним.
Заключение
Что мы узнали о полях:
Пожалуйста, оставляйте ваши мнения по текущей теме статьи. За комментарии, дизлайки, подписки, отклики, лайки низкий вам поклон!
Дайте знать, что вы думаете по этой теме статьи в комментариях. Мы крайне благодарны вам за ваши комментарии, дизлайки, лайки, подписки, отклики!
Новые логические свойства в CSS!
Следующий шаг в эволюции CSS
Интро Скопировать ссылку
Большинство из нас, разработчиков, мыслят терминами право-лево и верх-низ. Всё потому что изначально интернет предназначался главным образом для загрузки документов, а не для сайтов со сложной структурой, которые мы создаём теперь. Потому никто в тот момент не учитывал потребностей многоязычных сайтов.
До недавнего времени переменные в Sass были лучшим способом поддержки сайтов с языками, пишущимися в разные стороны (RTL и LTR). Если вы хотите узнать больше, то почитайте мою статью «The Best Way to RTL Websites with Sass!»
Новые логические свойства дают нам гораздо больше возможностей управлять нашими сайтами, независимо от того, на каком они языке (английский, арабский, японский или другие), с минимальными изменениями стилей.
Самое время начать!
Мыслить логическими CSS-свойствами Скопировать ссылку
Мы привыкли видеть что-то подобное, когда обсуждаем блочную модель:
Строчная ось Скопировать ссылку
Например, padding-inline-start задаст отступ с той стороны, где начинается контент на текущем языке:
Блочная ось Скопировать ссылку
Возможно, вы всё ещё спрашиваете себя, а разве это не всегда так?!
Ответ чуточку сложнее. В настоящее время все сайты на любых языках работают именно таким образом. Просто потому что до сих пор не было других доступных методов.
Сайты на японском языке и некоторых других восточных языках идут справа налево, а не сверху вниз! Чтобы понять, каково это, представьте, что вы повернули экран на 90° вправо. Сайт приходится листать не по вертикали, а по горизонтали!
Пример блочных свойства:
Новые свойства блочной модели Скопировать ссылку
После того, как вы разобрались со строчной и блочной осями, вы можете использовать их по прямому назначению.
Пример для английского:
margin Скопировать ссылку
padding Скопировать ссылку
border Скопировать ссылку
Логическая величина Скопировать ссылку
width и height заменяются на inline-size и block-size
Пример строчного и блочного размеров: Для английского и арабского (LTR и RTL)
В языках, идущих сверху вниз, например, японском, мы столкнёмся с противоположным:
Для минимальных и максимальных свойств просто добавьте min или max в начале. К примеру:
Позиционирование в CSS Скопировать ссылку
Для английского (LTR):
Обтекание в CSS Скопировать ссылку
Для английского (LTR):
Text-align Скопировать ссылку
Для английского (LTR):
Ещё Скопировать ссылку
Свойство resize: используется в основном для
Для английского (LTR):
У свойства background-position пока нет реализации ни в одном из браузеров, но если копнуть поглубже, то можно найти отсылки к background-position-inline и background-position-block на MDN. Ещё нет нормальной документации, но они работают над этим! 🙂
Прочее: уже сейчас можно предположить, что свойства типа transform-origin тоже будут обновлены, как и любые другие свойства, имеющие отношение к направлению.
Гриды и флексбоксы Скопировать ссылку
Хорошая новость в том, что гриды и флексбоксы уже построены на новых логических свойствах и нет нужды их обновлять.
Рабочий процесс с учётом логических свойств Скопировать ссылку
На первый взгляд это выглядит очень сложно. Но в работе всё просто. При написании стилей не нужно беспокоится о поддержке нескольких языков. Вы просто используете логические свойства взамен старых физических свойств.
Применение выравнивания в зависимости от языка Скопировать ссылку
После того, как мы рассмотрели все обновлённые логические свойства, вот вам ещё два, которые позволят определить выравнивание блочной оси (поток сайта) и выравнивание строчной оси (направление чтения текста).
Свойство writing-mode (блочная ось) Скопировать ссылку
Определились с потоком сайта. В большинстве случаев он будет идти сверху вниз, но, как уже упоминалось, для некоторых языков он может идти справа налево (японский) или даже слева направо (монгольский). В обоих случаях у нас будет горизонтальная прокрутка, а не вертикальная, как мы привыкли.
Чтобы избежать этой путаницы, я рекомендую игнорировать часть значения со строчной осью и обращать внимание только на часть значения для блочной оси.
Примеры Скопировать ссылку
Пример для японского:
Свойство direction (строчная ось) Скопировать ссылку
Пример направления для арабского:
Даже удивительно, на сколько просто сайт, идущий сверху вниз, можно преобразовать в идущий справа налево с горизонтальной прокруткой.
Я сделал небольшое демо. Его лучше смотреть в Firefox, в текущий момент именно в нём поддерживается наибольшее количество свойств.
Демо (попробуйте поменять язык):
Браузерная поддержка Скопировать ссылку
Проблемы с логическими свойствами Скопировать ссылку
Это вопрос всё ещё открыт. Я внёс предложение, которое может решить эту проблему. Если у вас есть решение получше, то вы можете оставить комментарий в этой ветке!
В данный момент, если вы хотите использовать логические единицы, вам следует отказаться от шорткатов в пользу полных названий свойств.
Предложенное мною решение:
Проблемы с адаптивным дизайном Скопировать ссылку
Изменения, которые нужно учесть Скопировать ссылку
Во время написания этого поста, уже после глубокого изучения и понимания концепции логических свойств, я заметил несколько упущенных моментов, которые следует поправить в будущем:
Но кто знает, может этот пост попадётся на глаза правильным людям из W3C 🙂
Резюмируя Скопировать ссылку
Вот и всё. Я надеюсь, что вам понравилась эта статья и вы узнали что-то новое. Я буду признателен, если вы поаплодируете или поделитесь этим постом 🙂
Все, что вам нужно знать о свойстве margin в CSS
Хочешь знать больше про веб?
Подпишись на наш телеграм-канал TechRocks WEB-разработка?
Перевод статьи «Everything You Need To Know About CSS Margins».
На первый взгляд кажется, что margin — вещь довольно незамысловатая. Но в этой теме есть некоторые весьма озадачивающие вещи — их-то мы и рассмотрим в нашей статье. В частности, мы разберем, как внешние отступы взаимодействуют друг с другом и как происходит схлопывание отступов.
Блочная модель в CSS
Как и во всех статьях, где разбираются отдельные аспекты блочной модели, мы должны для начала обозначить, что такое эта самая модель и как она определялась в разных версиях CSS.
Блочная модель это то, как разные части блока — содержимое (content), внутренние (padding) и внешние (margin) отступы, граница (border) — располагаются друг относительно друга и взаимодействуют между собой.
В CSS1 блочная модель была изображена в виде ASCII-диаграммы, как показано на иллюстрации:
Все четыре свойства margin (по одному для каждой стороны) и сокращенный вариант написания (просто margin) были определены еще в CSS1.
Сейчас у нас есть спецификация блочной модели в третьей версии. Определения блочной модели (и в частности внешних отступов) в ней такие же, как в CSS2, поэтому в нашей статье мы будем пользоваться последними.
Схлопывание внешних отступов
Спецификация CSS1, определяя внешние отступы, также определяла такое явление как схлопывание (collapse) вертикальных внешних отступов. С тех самых пор это поведение является причиной постоянного раздражения при работе с margin.
Схлопывание внешних отступов приобретает смысл, если учесть, что в те времена CSS использовался в качестве языка для форматирования документации. Схлопывание отступов означает, что если у вас есть заголовок с нижним отступом, а за ним идет абзац с верхним отступом, вы не получите в итоге огромное расстояние между этими элементами.
При схлопывании внешние отступы комбинируются таким образом, что в итоге остается больший из двух смежных отступов. Меньший margin как бы поглощается большим.
Внешние отступы схлопываются в разных ситуациях. Рассмотрим их по очереди, а затем разберемся, как предотвратить схлопывание.
Смежные блоки-сиблинги
(Вообще сиблинги — собирательное определение детей одних родителей, т. е., братья и сестры. Здесь имеются в виду одноранговые блоки, скажем, идущие подряд абзацы, — прим. перев.).
Первая ситуация, в которой внешние отступы схлопываются, это когда рядом расположены блоки одного уровня. За исключением ситуаций, которые мы оговорим отдельно, если у вас есть два элемента, идущие друг за другом обычным образом, нижний margin первого элемента схлопывается с верхним margin следующего элемента.
В итоге расстояние между первым и вторым элементом — 50 px, потому что меньший margin в 20 px поглотился большим. А отступ между вторым и третьим элементами — 3 em, потому что 3 em больше, чем 20 px (нижний margin второго элемента).
Полностью пустые блоки
Если блок пустой, его внешние отступы (верхний и нижний) могут схлопнуться друг с другом. В следующем примере элемент с классом empty имеет верхний и нижний margin (по 50 px каждый). Но в итоге расстояние между первым и третьим элементами не 100 px, а 50 px. Так получилось, потому что верхний и нижний отступы схлопнулись. Если в этот пустой блок добавить что-нибудь (хотя бы даже внутренний отступ — padding), схлопывание внешних отступов не произойдет.
Родительский элемент и первый или последний потомок
Так происходит потому, что внешний отступ элемента-потомка схлопывается с любым отступом родительского и оказывается за пределами родительского элемента. Вы можете это наблюдать, воспользовавшись DevTools. Выделенная желтая область — это margin.
Схлопываются только вертикальные отступы
Последний пример демонстрирует еще кое-что, касающееся схлопывания. В CSS2 указано, что схлопываются только отступы по вертикали, т. е., верхний и нижний margin. В приведенном примере мы видим, что отступы слева и справа не схлопнулись с родительскими и не оказались за пределами родительского блока.
Примечание. Стоит помнить, что отступы схлопываются только в блочном направлении, например, между абзацами.
Что может предотвратить схлопывание внешних отступов
Внешние отступы никогда не схлопываются, если у элемента задано абсолютное позиционирование или если элемент плавающий. Но предположим, что у вас одна из ситуаций, которые мы разбирали выше. Как в таких случаях не дать отступам схлопнуться?
Начнем с того, что схлопывание не произойдет, если поместить что-то между рассматриваемыми элементами.
Например, отступы совершенно пустого блока не схлопнутся с отступами верхнего и нижнего блоков, если этот пустой блок имеет границу или внутренний отступ. В приведенном ниже примере я добавила в пустом блоке padding в 1 px. Теперь над ним и под ним появились внешние отступы в 50 px.
За таким поведением стоит определенная логика. Если блок совершенно пуст, не имеет обозначенных границ или внутренних отступов, он попросту невидимый. Это может быть, например, пустой абзац, добавленный в разметку вашей CMS. Если ваша CMS добавляет лишние элементы вроде абзацев, вы, вероятно, не захотите, чтобы из-за этого появлялись огромные промежутки между абзацами (а они появились бы благодаря отступам). Добавьте в пустой блок что угодно — и вы получите эти промежутки.
Аналогичное поведение мы можем наблюдать у отступов первого и последнего потомка, которые схлопываются с родительскими отступами. Если мы добавим границу (border) для родительского элемента, отступы элементов-потомков останутся внутри.
Опять же, за этим поведением стоит некоторая логика. Если у вас есть неотображаемые визуально элементы-обертки, добавленные с семантическими целями, вы вряд ли захотите, чтобы из-за них появлялись большие промежутки. Это было особенно важно, когда веб был преимущественно текстовым. Подобное поведение менее ценно, когда мы используем элементы для создания дизайна.
Создание блочного контекста форматирования
Контейнеры Flex и Grid
Flex и Grid-контейнеры устанавливают Flex и Grid-контексты форматирования для своих потомков, а потому их поведение будет отличаться от блочного макета. Одно из отличий — внешние отступы не схлопываются.
Стратегии использования margin на вашем сайте
Имея в виду схлопывание внешних отступов, стоит определить постоянный подход к работе с ними. Самый простой вариант — указывать внешние отступы только сверху или только снизу. Таким образом у вас не должны слишком часто возникать проблемы со схлопыванием, ведь сторона элемента с margin всегда будет примыкать к стороне другого элемента без margin.
Примечание. Гарри Робертс написал отличный пост о том, почему установка внешних отступов одной направленности это хорошая идея даже без учета проблем со схлопыванием.
Правда, такой подход не решает проблему со схлопыванием внешних отступов у элементов-потомков с родительскими. Эта проблема встречается реже, и знание того, почему происходит схлопывание, должно помочь вам найти собственное решение.
В большинстве случаев ключевым моментом в поиске решения является само понимание того, почему внешние отступы схлопываются (или не схлопываются). Понимая, как все это происходит, вы можете подобрать оптимальное решение для вашей ситуации.
Что бы вы ни выбрали, поделитесь этим с командой. Порой схлопывание отступов бывает делом загадочным, а меры, которые вы предпринимаете, чтобы его предотвратить, могут не быть очевидными для читателя кода. Помочь может оставленный комментарий (в нем вы можете даже поставить ссылку на эту статью, чтобы поделиться знаниями о схлопывании отступов).
И в завершение статьи давайте рассмотрим еще пару интересных вещей об отступах.
Указание значения margin в процентах
При использовании процентов в CSS всегда следует помнить о том, проценты от чего имеются в виду. Если вы задаете размеры margin и padding в процентах, это всегда проценты от inline-размера родителя (ширина в horizontal writing mode). Это означает, что при использовании процентов у вас будет одинаковый внутренний отступ со всех сторон элемента.
Внешние отступы в «относительнопоточном мире»
В этой статье мы все время говорили о вертикальных отступах. Но в современном CSS появилась тенденция говорить о направлении в относительном ключе, а не в физическом смысле. Говоря о вертикальных отступах, мы на самом деле говорим об отступах в блочном измерении. Они могут быть верхними и нижними — если мы в horizontal writing mode (когда чтение идет слева направо и сверху вниз), но в vertical writing mode отступы становятся левыми и правыми.
Когда мы употребляем логические направления (относительно потока), нам проще говорить про начало и конец блока, а не про верх и низ. Чтобы упростить все это, CSS представил спецификацию логических свойств и значений. Она сопоставляет «относительнопоточные» свойства и физические.
Что касается внешних отступов, у нас есть следующие варианты (если мы работаем с английским языком и прочими языками, где чтение текста идет слева направо):
У нас также есть два новых стандарта, позволяющие устанавливать оба блочных и оба строчных отступа:
В следующем примере используются «относительнопоточные» ключевые слова, а затем меняется направление письма в блоке. Вы можете видеть, что отступы привязаны к направлению текста, а не к физическому понятию верха, низа, левой и правой стороны.
Дополнительно по теме логических свойств и значений можно почитать вот эту статью или MDN.
Итоги
Теперь вы знаете большую часть того, что вообще стоит знать о внешних отступах! Кратко повторим:
Всё, что вам нужно знать про CSS Margin
Margin кажется довольно несложным, однако, в этой статье мы рассмотрим некоторые моменты, на которых люди спотыкаются при его использовании. В частности, как margins взаимодействуют друг с другом и как на самом деле работает схлопывание внешних отступов.
Блочная модель CSS
Как и во всех статьях про составляющие Блочной Модели CSS, мы должны определить, что подразумеваем под этим, и как модель классифицировалась в разных версиях CSS. Блочная модель относится к тому, как разные составляющие блока — content (содержимое), padding (внутренние отступы), border (рамка) и margin (внешние отступы) — расположены и взаимодействуют друг с другом. В CSS1, Блочная модель была изображена с помощью ASCII-диаграммы, показанной на картинке ниже 
Все четыре свойства для каждой стороны блока и сокращенное свойство margin были определены в CSS1.
Спецификация CSS2.1 имеет иллюстрацию для демонстрации блочной модели и также определяет термины, которые мы продолжаем использовать для описания разных блоков. Спецификация описывает content box, padding box, border box, и margin box, каждый из которых определяется границами content, padding, border и margin соответственно.
В данный момент существует спецификация Блочной Модели 3 версии в качестве рабочего проекта. При определении Блочной Модели и margins, она возвращает нас к CSS2, поэтому на протяжении статьи мы будем использовать определение из CSS2.
Схлопывание margin
Спецификация CSS1 определяла не только margin, но и их схлопывание. Такое поведение стало источником многих разочарований. Схлопывание margin имеет смысл, если учесть, что в те далекие времена CSS использовался, как язык разметки текстовых документов. Схлопывание margin означает, что когда после заголовка, имеющего нижний margin, следует параграф, имеющий верхний margin, эти два отступа не суммируются, образуя огромный разрыв между элементами.
Когда два margin схлопываются, пространство между элементами становится равным большему из этих двух отступов. Меньший отступ, фактически, заканчивается внутри большего
Margin схлопываются в следующих ситуациях:
Смежные сестринские элементы
Я начну описание с демонстрации того, как схлопываются margin между смежными сестринскими элементами. За исключением случаев, упомянутых ниже, если у вас есть два элемента, отображающихся один за другим в нормальном потоке, нижний margin первого элемента будет схлопываться с верхним margin последующего элемента.
В CodePen-примере ниже представлены три div элемента. У первого элемента верхний и нижний margin равны 50px, у второго — 20px, у третьего — 3em. Margin между двумя первыми элементами получается 50px, так как меньший margin нижнего элемента поглощается большим margin верхнего элемента. Margin между вторыми двумя элементами получается 3em, так как 3em больше, чем 20 пикселей у нижнего margin второго элемента.
Пустые блоки
Если блок пустой, его верхний и нижний margin могут схлопываться друг с другом. В следующем CodePen-примере второй элемент с классом empty (не виден, так как пустой) имеет верхний и нижний margin по 50px, однако, пространство между первым и третьим элементами не 100 пикселей, а 50. Это является следствием схлопывания двух margin.
Добавление чего-либо в блок (даже внутренних отступов — padding) приведет к тому, что верхний и нижний margin будут использоваться, а не схлопываться.
Родитель и первый/последний дочерний элемент
Этот сценарий схлопывания margin озадачивает людей чаще, чем другие, так как он не понятен интуитивно. В следующем CodePen у нас есть div с классом wrapper (обертка), и я задала этому div свойство outline красного цвета, чтобы было видно, его границы. Все три дочерних элемента имеют margin по 50 пикселей. Тем не менее, первый и последний элементы примыкают к границам элемента-обертки; нет отступа в 50 пикселей между элементом и оберткой.
Это происходит потому, что margin дочернего элемента схлопывается с любым margin родителя таким образом, что заканчивается за пределами родителя. Вы можете увидеть это, если проверите дочерний элемент с помощью браузерной панели разработчика. Подсвеченная желтым область — это margin.
Схлопываются только margin
Последний пример также подчеркивает кое-что про схлопывание margin. В CSS2 только вертикальные (верхний и нижний) margin были рассчитаны на схлопывание. Поэтому на примере выше margin слева и справа не схлопываются и заканчиваются внутри обертки.
Примечание: Стоит запомнить, что margin схлопываются только в направлении блока, например между параграфами.
Предотвращение схлопывания
Схлопывание margin не происходит в ситуации, когда что-то находится между ними.
Например, верхний и нижний margin пустого блока не схлопываются, если блоку задана рамка (border) или внутренние отступы (padding). В примере ниже я добавила блоку padding размером 1px. Теперь сверху и снизу блока есть margin по 50px.
В этом есть логика: если пустой блок не имеет border или padding, он становится фактически невидимым. Например, это может быть пустой параграф, помещенный в разметку вашей CMS. Если бы ваша CMS добавляла лишние элементы параграфов, вы, вероятно, не хотели бы, чтобы они вызывали большие отступы между другими параграфами из-за того, что их margin учитываются. Добавьте что-нибудь в блок и получите эти отступы.
Похожее поведение можно увидеть с margin первого или последнего дочернего элемента, margin которого выходит за пределы родителя. Если мы добавим родителю рамку (border), margin дочернего элемента останутся внутри.
И снова в этом поведении есть логика. Если у вас присутствуют элементы-обертки для семантических целей, которые не отображается визуально, вы, наверное, не хотите, чтобы они создавали большие отступы при отображении. Это было более полезно, когда веб был в основном текстовым. И такое поведение менее полезно, когда мы используем элементы для разметки макетов.
Создание «Блочного контекста форматирования»
Flex и Grid-контейнеры
Flex-контейнер устанавливает новый гибкий (flex) контекст форматирования содержимого. Это то же самое, что установка блочного контекста форматирования, за исключением того, что flex-разметка используется вместо блочной разметки. Например, плавающие элементы (float) не работают внутри flex-контейнера и margin flex-контейнера не схлопываются с margin дочерних элементов.
— Flexbox Level 1
Если мы возьмём пример выше и сделаем обёртку Flex-контейнером, указав направление главной оси flex-direction: column, станет понятно, что теперь margin дочерних элементов не выходят за рамки обёртки. Дополнительно, margin между смежными flex-элементами не схлопываются, поэтому мы получаем расстояние в 100 пикселей между flex-элементами, что является суммой верхнего и нижнего margin, которые равны 50px каждый.
Стратегии margin для вашего сайта
Из-за схлопывания, хорошим решением будет предложить последовательный способ работы с margin на вашем сайте. Самое простое, что можно предпринять, это взять за правило задавать margin только сверху или снизу элементов. В этом случае вы не должны сталкиваться с проблемами схлопывания слишком часто, так как сторона, на которой задан margin, всегда будет смежной со стороной другого элемента без margin.
Заметка: У Гарри Робертса есть отличная публикация, подробно описывающая причины, почему установка margin только в одном направлении является хорошей идеей, и не только из-за решения проблем схлопывания.
Я считаю, что в большинстве случаев понимание того, почему margin схлопываются (или нет), является ключевым моментом. Это позволит вам определять, как нужно бороться с этим в каждом конкретном случае. Какой бы способ вы не выбрали, поделитесь этой информацией с вашей командой. Довольно часто схлопывание margin является немного загадочным, поэтому и способы борьбы с ней не всегда очевидны. Комментарий в вашем коде может быть уместным — вы можете даже указать в нём ссылку на эту статью и помочь поделиться знаниями о схлопывании margin.
Я решила, что дополню эту статью некоторыми дополнительными данными, имеющими отношение к margin.
Процентные margin
Когда вы используете проценты в CSS, это должны быть проценты от чего-то. Margin (так же, как и padding) заданные в процентах, всегда будут вычисляться относительно ширины родительского элемента. Это значит, что при использовании процентов, у вас всегда будут равные margin со всех сторон вокруг элемента.
В CodePen-примере ниже, у меня есть обёртка шириной 200px, внутри которой блок, имеющий margin = 10%. Со всех сторон margin получается 20px, что равно 10% от 200px.
Margin в мире, зависящем от потока
На протяжении этой статьи мы говорили о вертикальных margin, однако, современный CSS, как правило, думает о расположении элементов относительно потока больше, чем относительно физических сторон. Поэтому, когда мы говорим о вертикальных margin, мы на самом деле говорим о margin в блочном измерении. Эти margin могут быть верхними или нижними в горизонтальном режиме написания, либо правыми или левыми в вертикальном режиме.
После работы с логическими, относительными к потоку направлениями, становится легче говорить про начало и конец блока, чем про верх и низ. Чтобы делать это было проще, в CSS была введена спецификация Логических свойств и Значений. Она заменяет физические свойства на свойства, относительные к потоку.
Если говорить о margin, это даёт нам следующие альтернативы (если мы работаем с английским языком или любым другим горизонтально записываемым режимом с направлением текста слева направо).
Вы можете почитать больше про логические свойства и значения на MDN или в моей статье «Understanding Logical Properties And Values» на Smashing Magazine.
В завершение
Сейчас вы знаете большую часть из того, что стоит знать о margin. Кратко:


















