Справочник · CSS
margin: внешний отступ элемента
Свойство margin задаёт внешний отступ элемента: пустое место снаружи рамки, до соседа. Его пишут по сторонам или короткой записью. margin-inline: auto центрирует блок известной ширины. Вертикальные margin соседних блоков могут схлопнуться в один.
- margin — снаружи рамки, padding — внутри.
- Процент считается от ширины содержащего блока, даже у верхнего и нижнего margin.
- auto слева и справа центрирует блок с шириной.
- У строчных элементов вертикальный margin не сдвигает строку.
- Для промежутка во flex и grid чаще удобнее gap.
Минимальный пример
Карточке нужна пустота до следующего блока, не внутри рамки. Внутренние поля — это padding. Снаружи — margin.
.card {
width: 360px;
margin: 0 auto 32px;
padding: 16px;
}
Ноль сверху, автоматические боковые, 32px снизу. Карточка встанет по центру колонки, если у родителя есть ширина больше 360px.
Таблица записи сторон
| Запись | Верх | Право | Низ | Лево |
|---|---|---|---|---|
| margin: 16px | 16 | 16 | 16 | 16 |
| margin: 16px 8px | 16 | 8 | 16 | 8 |
| margin: 16px 8px 4px | 16 | 8 | 4 | 8 |
| margin: 16px 8px 4px 2px | 16 | 8 | 4 | 2 |
Порядок четырёх значений — сверху по часовой стрелке. Для логических свойств в новых макетах удобнее margin-inline и margin-block: они не ломаются при смене направления текста. Если страница когда-нибудь станет двуязычной с письмом справа налево, left/right придётся менять руками, а inline сам поменяется местами.
Проценты считаются от ширины родителя
Если написать margin: 10%, браузер возьмёт 10% ширины содержащего блока и применит это число ко всем сторонам, включая верх и низ. Высота родителя в эту формулу не входит. Поэтому вертикальный «отступ 10%» на мобильном уже, чем на десктопе, хотя страница стала длиннее. Если нужен отступ, связанный с высотой экрана, бери vh или фиксированные пиксели, не процент margin.
.hero { margin-top: 10%; } /* 10% ширины родителя, не высоты */
Вертикальный margin у строчных элементов
Ссылки, span, strong живут в строке. Горизонтальный margin раздвигает соседей в этой строке. Вертикальный margin для них не создаёт пустую полосу над и под строкой: высота строки считается по line-height и шрифту. Новичок ставит a { margin-top: 20px } и не видит сдвига. Решение: сделать ссылку кнопкой через display: inline-block или вынести её в блок.
a.button {
display: inline-block;
margin-top: 16px;
padding: 8px 12px;
}
Отрицательный margin
Отрицательное значение подтягивает элемент навстречу соседу. Пример: бейдж, который наезжает на угол картинки.
.badge {
display: inline-block;
margin-top: -12px;
margin-left: 12px;
}
Почему это опасный приём: элемент занимает в потоке одно место, а рисуется в другом. Соседний текст может оказаться под бейджем. В DevTools смотри реальную рамку и отдельно overflow родителя. Для наложения чаще предсказуемее position на общем контейнере.
Как центрировать блоком
Блок с заданной шириной центрируют так: margin-left: auto; margin-right: auto или margin-inline: auto. auto делит свободное место поровну. Без ширины блок и так растянут на 100%, делить нечего. Во flex-ряду auto на одной стороне прижимает элемент к противоположному краю — это тот же механизм, что шапка в уроке Flexbox.
Почему отступы схлопываются
Два соседних блока: у первого margin-bottom 24px, у второго margin-top 24px. В обычном потоке между ними будет 24px, не 48. Браузер берёт максимум. Схлопывание не действует горизонтально и обычно не действует между flex/grid-детьми. Чтобы соседние блоки не схлопывались, поставь родителю display: flex или grid с gap либо display: flow-root. Padding родителя разводит родителя с первым/последним ребёнком, но не два соседних margin между собой.
margin или padding
Пустота снаружи, до соседа. Фон элемента сюда не заходит.
Пустота внутри рамки. Фон и кликабельная область растут.
Частые ошибки
- Процент вертикального margin принимают за долю высоты.
- Ждут вертикальный сдвиг у
span. - Складывают в уме два вертикальных отступа, а они схлопнулись.
- Центрируют auto блок без width.
- Рисуют сетку карточек margin-ами и ловят кривой крайний зазор.
Доступность
Отступ не заменяет структуру. Заголовок и абзац всё равно должны быть тегами, а не «визуально отодвинутым текстом». Клику нужна площадь: лучше padding на кнопке, чем огромный margin вокруг тонкой ссылки.
Поддержка браузерами
margin есть везде. Логические свойства margin-inline поддерживаются современными браузерами; для очень старых пиши left/right. Отрицательные значения тоже старые и работают давно. Сверяй конкретное свойство на Can I use, не главную страницу сервиса.
Практика
Собери блок шириной 360px, центрируй его auto. Соседу сверху задай margin-bottom 24px, этому — margin-top 24px и измерь расстояние в DevTools: должно быть 24, не 48. Затем повесь 10% margin-top и поменяй ширину окна: отступ должен меняться вместе с шириной, не с высотой. Отдельно проверь span с margin-top: он не должен толкать абзац.
Частые вопросы
От чего считаются проценты в margin?
От ширины содержащего блока, не от высоты. Поэтому margin-top: 10% на узкой колонке меньше, чем на широкой, даже если высота страницы огромная. Это классическая ловушка.
Почему margin-top у span ничего не делает?
У строчных элементов вертикальные margin не влияют на высоту строки. Горизонтальные работают. Чтобы сдвинуть по вертикали, сделай элемент блочным или inline-block, либо используй padding и line-height.
Когда писать отрицательный margin?
Чтобы пододвинуть блок к соседу или вытащить его из потока на несколько пикселей, например нахлест карточки на картинку. Легко сломать адаптив: на узком экране нахлест может закрыть текст. Сначала попробуй transform или общий родитель.
Почему два отступа не сложились?
Соседние вертикальные margin блоков схлопнулись: остался больший. Горизонтальные не схлопываются. Внутри flex и grid вертикальное схлопывание не работает как в обычном потоке.
Чем gap лучше margin в ряду карточек?
gap задаёт промежуток между детьми и не вылезает наружу контейнера. Margin на детях легко даёт лишний зазор с краю.