← Назад к вопросам

Что такое схлопывание padding?

1.3 Junior🔥 151 комментариев
#HTML и CSS

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое схлопывание padding?

Вероятно, здесь имеется в виду схлопывание margin (margin collapse), а не padding. Это одна из самых запутанных концепций в CSS, которая часто застаёт разработчиков врасплох.

Важное уточнение

Padding НИКОГДА не схлопывается. Padding всегда добавляет пространство внутри элемента. Схлопывание происходит только с margin — внешним отступом.

Возможно, интервьюер имел в виду именно margin collapse, или вопрос содержит опечатку.

Что такое Margin Collapse (схлопывание margin)

Margin collapse — это поведение, когда два смежных margin'а объединяются в один. Вместо того чтобы складываться, они принимают максимальное значение из двух.

.parent {
  background: lightblue;
}

.child {
  margin-top: 20px;
  background: lightcoral;
}

.sibling {
  margin-bottom: 30px;
  margin-top: 10px;
}

/* Что мы ожидаем:
   - Между child и sibling: 20px + 30px = 50px
   
   Что происходит на самом деле:
   - Между child и sibling: max(20px, 30px) = 30px
*/

Три сценария схлопывания margin

1. Margin между соседними элементами (sibling)

<div class="box1">Box 1</div>
<div class="box2">Box 2</div>
.box1 {
  margin-bottom: 30px;
}

.box2 {
  margin-top: 20px;
}

/* Ожидаемое расстояние: 30px + 20px = 50px
   Реальное расстояние: max(30px, 20px) = 30px
*/

2. Margin между родителем и первым дочерним элементом

Это самый запутанный сценарий!

<div class="parent">
  <div class="child">Child</div>
</div>
.parent {
  background: lightblue;
  /* Нет padding, border и inline content */
}

.child {
  margin-top: 30px;
  background: lightcoral;
}

/* Вместо того чтобы сдвинуть child на 30px внутри parent,
   margin сдвигает весь parent на 30px! */

Визуально:

Без margin-top: parent и child соприкасаются
С margin-top: 30px — весь parent сдвигается на 30px вниз!

3. Margin пустого элемента

Если элемент пуст, его верхний и нижний margin схлопываются в один.

.empty {
  margin-top: 20px;
  margin-bottom: 30px;
}

/* Результирующий margin: max(20px, 30px) = 30px */

Пример проблемы

<section class="container">
  <h1>Заголовок</h1>
  <p>Текст</p>
</section>

<section class="container">
  <h1>Ещё заголовок</h1>
</section>
.container {
  background: #f0f0f0;
  /* Нет padding или border */
}

h1 {
  margin-top: 0;
  margin-bottom: 20px;
}

p {
  margin-top: 20px;
}

section {
  margin-bottom: 30px;
}

/* Что происходит:
   1. Между первой h1 и section: margin-bottom section (30px) схлопывается с margin-bottom h1 (20px) = 30px
   2. Между section'ами: 30px + 30px = 30px (схлопываются)
   3. p и h1 второй section: 20px (схлопываются)
*/

Когда margin НЕ схлопывается

1. Если родитель имеет padding

.parent {
  padding-top: 1px; /* Даже 1px останавливает collapse */
}

.child {
  margin-top: 30px; /* Теперь это работает как ожидается */
}

2. Если родитель имеет border

.parent {
  border-top: 1px solid transparent; /* Останавливает collapse */
}

.child {
  margin-top: 30px;
}

3. Если родитель имеет inline content

<div class="parent">
  Текст здесь
  <div class="child">Child</div>
</div>
/* margin-top child не схлопывается, потому что есть текст */

4. Если используется display: flex или grid

.parent {
  display: flex; /* Отменяет margin collapse */
}

.child {
  margin-top: 30px; /* Теперь работает как ожидается */
}

5. Если элемент имеет overflow: auto/hidden

.parent {
  overflow: hidden; /* Создаёт Block Formatting Context (BFC) */
}

.child {
  margin-top: 30px;
}

Как остановить margin collapse

Способ 1: Добавить padding родителю

.parent {
  padding-top: 1px; /* Минимальное значение */
}

Способ 2: Добавить border родителю

.parent {
  border-top: 1px solid transparent;
}

Способ 3: Использовать display: flex или grid

.parent {
  display: flex;
  flex-direction: column;
}

Способ 4: Использовать overflow

.parent {
  overflow: hidden; /* или auto */
}

Способ 5: Использовать CSS Grid

.parent {
  display: grid;
  grid-template-columns: 1fr;
}

Практический пример: распространённая ошибка

<body>
  <header>Header</header>
</body>
header {
  margin-top: 20px;
  background: blue;
}

/* Вместо того чтобы сдвинуть header на 20px внутри body,
   margin сдвинет весь header относительно viewport,
   потому что body не имеет padding/border! */

Исправление:

body {
  padding: 0; /* Явно устанавливаем */
}

header {
  margin-top: 20px; /* Теперь работает как ожидается */
}

/* Или используем padding для header вместо margin */
header {
  padding-top: 20px;
  margin-top: 0;
}

Почему это существует?

Margin collapse — это намеренное поведение, спроектированное для типографики. В документе с абзацами часто бывает сложно предсказать отступы, поэтому схлопывание упрощает жизнь.

<article>
  <h1>Заголовок</h1>
  <p>Первый абзац</p>
  <p>Второй абзац</p>
</article>
artcle {
  /* Нет padding/border */
}

h1 {
  margin-bottom: 20px;
}

p {
  margin-top: 20px;
  margin-bottom: 20px;
}

/* С collapse: расстояние между элементами всегда 20px (max)
   Без collapse: было бы 20px + 20px = 40px (некрасиво)
*/

Современное решение: gap в Grid и Flexbox

Вместо margin используй gap:

.container {
  display: flex;
  flex-direction: column;
  gap: 20px; /* Единообразный отступ, без collapse */
}

.item {
  margin: 0; /* Не нужны margin'ы */
}

Это более предсказуемо и избегает margin collapse проблем.

Отладка

// Консоль DevTools
const element = document.querySelector('.child');
const styles = window.getComputedStyle(element);
console.log('Computed margin-top:', styles.marginTop);

// Также смотри в DevTools Inspector на вкладке Box Model
// Там видно точное расположение margin'ов

Резюме

  1. Margin collapse происходит только с margin, не с padding
  2. Два соседних margin'а объединяются в больший из них
  3. Margin дочернего элемента может "выпрыгнуть" за границы родителя
  4. Flex, Grid, padding, border, overflow останавливают collapse
  5. Современный подход: используй gap вместо margin для списков

Это одна из самых сложных особенностей CSS, даже опытные разработчики иногда спотыкаются об неё!