Как задать внешний отступ в CSS: свойство margin и схлопывание отступов

margin задаёт отступ снаружи рамки элемента, до соседей - его сокращённая запись работает так же, как у padding (см. предыдущий урок), но у margin есть два отличия: он может быть отрицательным, а вертикальные margin соседних блочных элементов не складываются, а схлопываются - берётся большее из двух значений.

Попробуй прямо сейчас: посмотри на зазор между блоками - он равен 30px (большему значению), а не 50px (сумме). Смени margin-top у .b на 40px - зазор станет 40px.

Как задать margin: та же запись, что у padding, но можно в минус

margin понимает ту же сокращённую запись, что и padding: одно значение - на все стороны, два - верх/низ и право/лево, три и четыре - по тому же принципу (см. предыдущий урок). Главное отличие: margin разрешает отрицательные значения, а padding - нет. Отрицательный margin сдвигает элемент в обратную сторону, как бы "вытягивая" его за пределы обычного места.

margin-top: -10px; - элемент сдвинется на 10px вверх относительно своего обычного положения.

padding: -10px; в попытке добиться того же эффекта - padding отрицательным быть не может, значение просто проигнорируется (см. урок про padding).

margin: auto и центрирование блока по горизонтали

Значение auto у margin-left и margin-right (или сокращённо margin: 0 auto) - классический способ отцентрировать блочный элемент по горизонтали. Браузер сам поровну распределяет свободное место слева и справа. Но это работает только если у элемента явно задана ширина (width) - без неё блочному элементу просто нечего центрировать, он и так растягивается на всю доступную ширину.

width: 300px; margin: 0 auto; - блок шириной 300px окажется точно по центру родителя.

margin: 0 auto; без width - у обычного блочного элемента (div) нет эффекта, он и без того занимает всю ширину родителя.

Схлопывание margin: почему соседние отступы не складываются

Когда margin-bottom одного блочного элемента соприкасается с margin-top следующего (без border, padding или контента между ними), они не складываются, а схлопываются - в итоге получается ОДИН отступ, равный БОЛЬШЕМУ из двух значений. Это касается только вертикальных отступов между обычными блочными соседями - горизонтальные margin (слева/справа) никогда не схлопываются, они всегда просто складываются, как ожидалось бы интуитивно.

margin-bottom: 30px; у первого блока и margin-top: 20px; у второго - реальный зазор между ними будет 30px, а не 50px.

Расчёт на то, что отступы сложатся (30+20=50px) - для вертикальных margin соседних блоков это не так, они схлопываются в максимум.

Из истории Схлопывание margin - тоже не позднее усложнение, а часть CSS с самого первого стандарта: CSS1 от 17 декабря 1996 года дословно говорит про соприкасающиеся вертикальные отступы: "collapsed to use the maximum of the margin values" - именно максимум, а не сумма, уже почти 30 лет. Источник: w3.org - CSS1, раздел про margin, 1996.

Частые ошибки новичков

ОшибкаЧто происходитКак исправить
Ожидают, что соседние вертикальные margin сложатся (например 30px + 20px = 50px) На самом деле получится 30px - большее из двух значений, а не сумма Закладывать в расчёты именно бОльшее из двух значений margin, а не сумму
Пытаются центрировать блок через margin: auto, не задав ему явную ширину Без width блочный элемент и так занимает всю ширину родителя - центрировать нечего Обязательно задать width (или max-width) вместе с margin: 0 auto
Ожидают схлопывания и для горизонтальных margin (слева/справа) Горизонтальные margin никогда не схлопываются, они всегда складываются Закладывать сумму, а не максимум, для margin-left и margin-right
Удивляются, что вертикальные margin внутри flex-контейнера ведут себя иначе Элементы flex (и grid) контейнера никогда не схлопывают margin между собой, даже по вертикали Учитывать, что схлопывание - поведение обычных блочных элементов, а не универсальное правило CSS

Шпаргалка

Что нужноКак сделать
Одинаковый отступ со всех сторонmargin: 20px;
Отступ только с одной стороныmargin-left: 20px;
Отрицательный отступ (сдвиг элемента)margin-top: -10px;
Центрировать блок с заданной ширинойwidth: 300px; margin: 0 auto;
Зазор между соседними блоками (вертикаль)больше из двух margin, а не сумма (схлопывание)
Зазор между соседними блоками (горизонталь)сумма двух margin - схлопывания нет

Коротко: отвечаем на вопросы

Как бороться со схлопыванием (сливанием) margin, если оно мешает вёрстке?

Проще всего добавить между блоками хоть немного border или padding - тогда margin уже не будут "соприкасаться" напрямую и схлопывание не сработает. Ещё один рабочий вариант - перевести родителя на display: flex или grid: у элементов внутри такой раскладки margin между собой никогда не схлопываются.

Почему margin: 0 auto не центрирует мой блок?

Самая частая причина - у элемента не задана явная ширина (width или max-width). Без неё блочный элемент и так растягивается на всю ширину родителя, и центрировать буквально нечего. Добавление конкретного width обычно сразу решает проблему.

Категория
css
Поделиться в социальных сетях

Отправить комментарий

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×