Для каких соседних элементов не работает схлопывание margin

Содержание
  1. Схлопывающиеся отступы
  2. Оба отступа положительны
  3. нижний отступ задаётся как 20 пикселов, а у
  4. Один из отступов отрицательный
  5. нижний отступ задаётся как 20 пикселов, а у
  6. отнимается значение верхнего отступа
  7. Оба отступа отрицательны
  8. нижний отступ задаётся как 1em , а у
  9. Вложенные элементы
  10. нижний отступ задаётся как 20px , у
  11. Отмена схлопывания
  12. , верхний отступ у которого устанавливается по умолчанию.
  13. и заменить его на padding-top при необходимости. Использование свойства overflow со значением auto также даст необходимый эффект. Ниже все эти методы сведены воедино.
  14. Обходим схлопывание margin
  15. Задача
  16. Решения
  17. Убираем схлопывание между смежными элементами
  18. Недостаток
  19. Убираем схлопывание между родителем и дочерними элементами
  20. Недостатки
  21. Недостатки
  22. Убираем схлопывание как между смежными элементами, так и между родителем и дочерними элементами
  23. Недостатки
  24. Недостатки
  25. Недостаток
  26. Недостаток
  27. Выводы
  28. Всё, что вам нужно знать про CSS Margin
  29. Блочная модель CSS
  30. Схлопывание margin
  31. Смежные сестринские элементы
  32. Пустые блоки
  33. Родитель и первый/последний дочерний элемент
  34. Схлопываются только margin
  35. Предотвращение схлопывания
  36. Создание «Блочного контекста форматирования»
  37. Flex и Grid-контейнеры
  38. Стратегии margin для вашего сайта
  39. Процентные margin
  40. Margin в мире, зависящем от потока
  41. В завершение

Схлопывающиеся отступы

При рассмотрении блочной модели была затронута тема схлопывания отступов. Этот эффект наблюдается, когда у блочных элементов расположенных рядом друг с другом по вертикали, отступы не суммируются, а объединяются между собой. Само схлопывание действует на два и более блока (один может быть вложен внутрь другого) с отступами сверху или снизу, при этом примыкающие отступы комбинируются в один. Этот эффект работает только для блоков, у которых не заданы поля и границы. Для отступов слева и справа схлопывание никогда не применяется.

Несмотря на загадочность, схлопывание несёт в себе сугубо практическое значение и в первую очередь предназначено для корректного отображения текста. Расстояние между абзацами (тег

) без схлопывания увеличится в два раза, тогда как верхний отступ первого абзаца и нижний отступ последнего абзаца останутся неизменными. Схлопывание гарантирует, что расстояние в абзацах везде будет одинаковым.

Правила вычисления единого отступа меняются в зависимости от ряда условий, так, есть разница между положительным и отрицательным значением отступа, родительским и дочерним элементом. Далее перечислим типовые примеры.

Оба отступа положительны

Для положительных значений отступов выбирается наибольшее значение из двух отступов, и оно устанавливается как расстояние между блоками. На рис. 3.13 пунктирной линией выделены отступы у блоков и показано как в этом случае блоки устанавливаются относительно друг друга.

Рис. 3.13. Разные отступы у блоков

При одинаковых значениях отступов за расстояние между блоками принимается одно из них.

В следующем стиле у тега

нижний отступ задаётся как 20 пикселов, а у

верхний отступ как 5 пикселов.

Значения отступов сравниваются между собой, и остаётся наибольшее число, расстояние между заголовком и абзацем текста принимается равным 20 пикселов (рис. 3.14).

Рис. 3.14. Положительные отступы

Один из отступов отрицательный

В этом случае происходит складывание отступов по правилам математики:

Здесь x и y величина прилегающих отступов элементов.

В следующем стиле у тега

нижний отступ задаётся как 20 пикселов, а у

верхний отступ с отрицательным значением 10 пикселов.

Из значения нижнего отступа тега

отнимается значение верхнего отступа

, в итоге расстояние между заголовком и абзацем текста будет равно 10 пикселов (рис. 3.15).

Рис. 3.15. Один отступ отрицательный

Если полученное значение в результате суммирования окажется отрицательным, то оно будет действовать на нижний блок, соответственно, он сдвинется вверх на указанное значение.

Оба отступа отрицательны

Из двух значений выбирается наибольшее по модулю, оно же и выступает в качестве отрицательного отступа между элементами. Так, если отступы равны -10px и -20px, то итоговое значение будет -20px.

В следующем стиле у тега

нижний отступ задаётся как 1em , а у

верхний отступ с отрицательным значением 10 пикселов.

При использовании разных единиц в отступах, браузер приводит их к одним единицам и сравнивает между собой. В данном случае 1em больше, чем 10px , поэтому текстовый абзац сдвинется вверх на 1em (рис. 3.16).

Рис. 3.16. Отрицательные отступы

Вложенные элементы

Предположим, что в нижнем блоке располагается дочерний элемент, у которого задан верхний отступ. Из блочной модели следует, что такой отступ сдвигает дочерний элемент вниз относительно верхнего края родителя. Однако с учётом схлопывающихся отступов результат будет иным. Отступ словно выйдет за пределы блока и будет задавать расстояние между верхним блоком и родительским элементом (рис. 3.17).

Рис. 3.17. Отступы с учётом дочернего элемента

В следующем стиле у тега

нижний отступ задаётся как 20px , у

На элементы воздействует сразу три разных отступа. Чтобы сделать расчет итогового отступа в такой сложной ситуации, можно действовать последовательно. Вначале определяем отступ между

. Оба значения положительны, при этом верхний отступ у

наибольший, он и будет итоговым отступом между

Рис. 3.18. Отступы с учётом вложения тегов

Схлопывание с вложенными тегами работает и без наличия верхнего элемента. Если оставить только конструкцию

Браузер Internet Explorer до версии 7.0 включительно не схлопывает отступы для элементов, у которых установлено свойство hasLayout . В частности, один из способов установить это свойство, это задать ширину для блока (свойство width ). Подробнее об этом смотрите главу посвященную IE.

Отмена схлопывания

Схлопывание не всегда требуется при вёрстке страницы, а в некоторых случаях вообще «ломает» дизайн. Поэтому следует знать, в каких случаях схлопывание работает, а в каких нет.

Схлопывание не срабатывает:

  • для элементов, у которых установлено свойство padding .
  • для элементов, у которых на стороне схлопывания задана граница;
  • на элементах с абсолютным позиционированием, т.е. таких, у которых position установлено как absolute ;
  • на плавающих элементах (для них свойство float задано как left или right );
  • для строчных элементов;
  • для .
Читайте также:  Почему может не работать слив у стиральной машины

Также схлопывание не срабатывает при соблюдении некоторых условий:

  • для элементов, у которых значение overflow задано как auto , hidden или scroll схлопывание не действует для их дочерних элементов;
  • у элементов, к которым применяется свойство clear, не схлопывается верхний отступ с нижним отступом родительского элемента.

В качестве примера возьмём достаточно распространённый случай, когда нам требуется сделать два слоя, у которых задан только фоновый цвет, но нет полей и границ (пример 3.9).

Пример 3.9. Близлежащие блоки

XHTML 1.0 CSS 2.1 IE Cr Op Sa Fx

Хотя у слоёв не заданы отступы, между ними появится небольшой промежуток (рис. 3.19). Он возникает из-за действия отступа у дочернего элемента

, верхний отступ у которого устанавливается по умолчанию.

Рис. 3.19. Отступ между слоями

Для обнуления появившегося отступа, который нам на самом деле не нужен, есть разные пути. Поскольку схлопывание не работает для блоков с полями и границами, можно задать значение padding для слоя content . Главное, чтобы значение было больше нуля, подойдет даже 1px . Также добавление границы ко всем сторонам или только линии для верхнего края отменит схлопывание. Ещё один способ — обнулить верхний отступ у

и заменить его на padding-top при необходимости. Использование свойства overflow со значением auto также даст необходимый эффект. Ниже все эти методы сведены воедино.

Поскольку отступы довольно активно применяются в вёрстке, их схлопывание может оказать принципиальное значение на вид документа. Учитывайте этот эффект при формировании блоков.

Источник

Обходим схлопывание margin

В некоторых случаях вертикальные внешние отступы (margin-top и margin-bottom) смежных элементов или родителя и первого/последнего потомка могут схлопываться. Подробнее об этом читай в статье Схлопывание margin.

Иногда схлопывание отступов мешает. Давай посмотрим, как от него можно избавится.

Задача

Решения

Вариантов решения много. У каждого есть своя область применения, свои особенности и, к сожалению, свои недостатки.

Убираем схлопывание между смежными элементами

Самый простой способ, не обходить схлопывание, а сделать так, чтобы его не могло быть в принципе, т.е. исключить ситуацию, когда рядом идут два отступа. Например, для смежных элементов задаем только margin-bottom или только margin-top.

Недостаток

  • Такой подход очень негибкий. Для первого или последнего элемента отступ придется определять дополнительно, возможно с использованием псевдокласcов :first-child или :last-child, которые поддерживаются не всеми браузерами (:first-child не понимает IE6, а :last-child не понимает ни IE6, ни IE7).

Убираем схлопывание между родителем и дочерними элементами

Для родительского элемента с нужной стороны задаем однопиксельный padding или однопиксельный прозрачный border (для IE6 задаем границу фоновым цветом элемента). Учти, что высота элемента при этом увеличивается на 1px!

Недостатки

  • Если высота у элемента жестко задана, нужно исправлять значение высоты для IE6 в режиме обратной совместимости.
  • IE6 не поддерживает прозрачный цвет границ, для него нужно задавать границу фоновым цветом элемента — имеем лишнее правило.
  • Для родителя задаем overflow со значением отличным от visible.

    Недостатки

    • Чтобы overflow заработало, у элемента должен быть четко прописан хотя бы один из размеров;
    • Нежелательный эффект от применения overflow (контент либо обрезается либо прокручивается, а это может не соответствовать задумке дизайнера).
  • Убираем схлопывание как между смежными элементами, так и между родителем и дочерними элементами

    Вместо одного или обоих вертикальных margin ставим границы (border) аналогичного размера. Цвет границ должен совпадать с цветом фона родителя для создания эффекта прозрачного пространства.

    Недостатки

    • Не очень красивое решение: границы должны использоваться в качестве границ, а не в качестве отступов.
    • Если у элементов уже заданы границы, то этот способ неприменим.
    • Способ неприменим, если элемент расположен на неоднородном фоне.
    • Если у элемента кроме внутреннего отступа жестко задана еще и высота, нужно исправлять значение высоты для IE6 в режиме обратной совместимости.
  • Вместо одного или обоих вертикальных margin ставим внутренние отступы элемента padding.

    Недостатки

    • Можно применять не всегда. Внутренний отступ залит фоновым цветом элемента, а внешний отступ — нет. Если по дизайну элемент имеет свою раскраску, этот метод неприменим.
    • Если у элемента кроме внутреннего отступа жестко задана еще и высота, нужно исправлять значение высоты для IE6 в режиме обратной совместимости.
  • Позиционируем элемент абсолютно (position:absolute;).

    Недостаток

    • Абсолютно спозиционированный элемент выпадает из потока, а это, в большинстве случаев, нежелательно.
  • Делаем элемент плавающим (float).

    Недостаток

    • Как и в предыдущем случае, плавающий элемент выпадет из потока, что может доставить лишние хлопоты с позиционированием последующих элементов.
  • Update 24.10.2010 by SelenIT. Задаем для элемента, участвующего в схлопывании, свойство display:inline-block/table/inline-table/table-cell.
  • Выводы

    Схлопывание margin между смежными элементами, как правило, позволяет более удобно реализовать отступы в контентной части. А вот ситуация, когда схлопываются вертикальные отступы дочернего и родительского элемента, чаще всего нежелательна. Существует ряд способов обойти схлопывание. Стоит ли это делать, и какой способ выбрать — решаем для каждого конкретного случая отдельно.

    Источник

    Всё, что вам нужно знать про CSS Margin

    Sep 10, 2019 · 8 min read

    Одним из первых, что многие из нас усвоили, когда изучали CSS, были особенности разных составляющих блока в CSS, описываемые как «Блочная Модель CSS». Один из элементов в блочной модели — margin (внешний отступ), прозрачная область вокруг блока, которая отталкивает другие элементы от содержимого данного блока. Свойства margin-top , margin-right , margin-bottom и margin-left были описаны еще в CSS1, вместе с сокращенным свойством 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 не схлопываются, если элементу задано абсолютное позиционирование или свойство float . Однако, если вы попали в ситуацию, когда margin схлопываются, как это предотвратить?

    Схлопывание margin не происходит в ситуации, когда что-то находится между ними.

    Например, верхний и нижний margin пустого блока не схлопываются, если блоку задана рамка (border) или внутренние отступы (padding). В примере ниже я добавила блоку padding размером 1px. Теперь сверху и снизу блока есть margin по 50px.

    В этом есть логика: если пустой блок не имеет border или padding, он становится фактически невидимым. Например, это может быть пустой параграф, помещенный в разметку вашей CMS. Если бы ваша CMS добавляла лишние элементы параграфов, вы, вероятно, не хотели бы, чтобы они вызывали большие отступы между другими параграфами из-за того, что их margin учитываются. Добавьте что-нибудь в блок и получите эти отступы.

    Похожее поведение можно увидеть с margin первого или последнего дочернего элемента, margin которого выходит за пределы родителя. Если мы добавим родителю рамку (border), margin дочернего элемента останутся внутри.

    И снова в этом поведении есть логика. Если у вас присутствуют элементы-обертки для семантических целей, которые не отображается визуально, вы, наверное, не хотите, чтобы они создавали большие отступы при отображении. Это было более полезно, когда веб был в основном текстовым. И такое поведение менее полезно, когда мы используем элементы для разметки макетов.

    Создание «Блочного контекста форматирования»

    Новый «Блочный контекст форматирования» (BFC) предотвратит выпадение margin за пределы родительского элемента. Если мы снова посмотрим на пример с первым и последним дочерними элементами, margin которых выпадают за пределы элемента-обёртки, и зададим обёртке display: flow-root , создав таким образом BFC, margin дочерних элементов останутся внутри.

    Читайте также:  Не работает один беспроводной наушник tws aceline basic

    Чтобы узнать больше о display: flow-root , читайте мою статью «Understanding CSS Layout And The Block Formatting Context». Изменение значения свойства overflow на auto будет иметь такой же эффект, поскольку это также создает новый BFC, хотя он может приводить к появлению полос прокрутки, которые не нужны в определенных случаях

    Flex и Grid-контейнеры

    Flex и Grid-контейнеры устанавливают Flex и Grid контекст форматирования для дочерних элементов, поэтому у них разное поведение блочной разметки. Одно из этих отличий заключается в том, что margin не схлопываются:

    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 дочерних элементов за пределы родителя, с которой вы можете столкнуться. Эта конкретная проблема, как правило, менее распространена и понимание того, почему это происходит, может помочь найти решение. Идеальное решение проблемы заключается в том, чтобы компонентам, которые требуют этого, задать display: flow-root , а фолбеком (запасным вариантом) для старых браузеров вы можете использовать overflow , чтобы создать BFC (блочный контекст форматирования); превратить родительский элемент во flex-контейнер; или даже задать padding размером 1px. Не забывайте, что вы можете использовать запрос поддержки свойств браузером (support), чтобы определить, поддерживается ли свойство display: flow-root , чтобы только старые браузеры получили менее оптимальное решение.

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

    • margin-top = margin-block-start
    • margin-right = margin-inline-end
    • margin-bottom = margin-block-end
    • margin-left = margin-inline-start

    У нас также есть два новых сокращенных свойства:

    В следующем CodePen-примере я использовала относительные к потоку ключевые слова и потом меняла режим написания блока. Вы можете видеть, как margin следуют за текстовым потоком, а не привязаны к физическим сторонам.

    Вы можете почитать больше про логические свойства и значения на MDN или в моей статье “Understanding Logical Properties And Values” на Smashing Magazine.

    В завершение

    Сейчас вы знаете большую часть из того, что стоит знать о margin. Кратко:

    • Margin могут схлопываться. Понимание, когда это происходит, а когда нет, поможет вам решить любые проблемы, которые они могут создать
    • Установка margin только в одном направлении решает много проблем, связанных с ними
    • Как и в любой другой ситуации, связанной с CSS, делитесь со своей командой решениями, которые принимаете, и комментируйте свой код
    • Учитывание блочных и строчных измерений вместо физических сторон верх, право, низ и лево, поможет вам, так как веб движется к тому, чтобы стать независимым от режима написания

    Источник

    Оцените статью