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

В каком случае схлопывание внешних отступов не сработает

1.8 Middle🔥 141 комментариев
#HTML и CSS

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

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

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

Схлопывание внешних отступов (Margin Collapse)

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

Margin collapse (схлопывание внешних отступов, коллапс маржинов) — это CSS механизм, при которой два соседних вертикальных margin объединяются в один, равный большему из двух.

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

Пример схлопывания (что происходит)

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

.box2 {
  margin-top: 30px;
}

Что вы ожидаете: расстояние между box1 и box2 = 20px + 30px = 50px

Что на самом деле: расстояние = 30px (берётся больший margin)

Когда происходит схлопывание

Маржины схлопываются только в следующих случаях:

1. Соседние блоки (adjacent siblings)

<p>Первый параграф (margin-bottom: 20px)</p>
<p>Второй параграф (margin-top: 30px)</p>

Маржины схлопываются: расстояние = 30px (больший)

2. Родитель и его первый/последний ребёнок

<div class="parent">
  <p class="child">Абзац</p>
</div>
.parent {
  margin-top: 20px;
}

.child {
  margin-top: 10px;
}

Маржины схлопываются: margin-top parent = 20px (больший)

3. Пустые блоки

Если блок не имеет содержимого, его margin-top и margin-bottom схлопываются:

<div class="empty" style="margin-top: 20px; margin-bottom: 30px;"></div>

Итоговый margin = 30px (больший)

Когда схлопывание НЕ происходит

1. Горизонтальные маржины НИКОГДА не схлопываются

.box1 {
  margin-right: 20px;
}

.box2 {
  margin-left: 30px;
}

/* Расстояние = 20px + 30px = 50px (складываются, не схлопываются) */

2. При наличии border или padding у родителя

<div class="parent" style="border: 1px solid black;">
  <p style="margin-top: 20px;">Абзац</p>
</div>
/* Маржин child НЕ схлопывается с маржином родителя
   потому что у родителя есть border */

3. При наличии padding у родителя

<div class="parent" style="padding-top: 10px;">
  <p style="margin-top: 20px;">Абзац</p>
</div>
/* Маржин child НЕ схлопывается
   потому что у родителя есть padding */

4. Для элементов с overflow != visible

<div class="parent" style="overflow: auto;">
  <p style="margin-top: 20px;">Абзац</p>
</div>
/* overflow: auto, hidden, scroll запрещает collapse */

5. Для flex и grid контейнеров

<div class="flex-container" style="display: flex;">
  <p style="margin-top: 20px;">Элемент</p>
</div>
/* display: flex, grid, inline-flex, inline-grid
   запрещают collapse маржинов */

6. Для inline и inline-block элементов

<span style="margin-top: 20px;">Текст</span>
/* display: inline НЕ поддерживает margin-top/bottom вообще
   display: inline-block маржины НЕ схлопываются */

7. Для позиционированных элементов (absolute, fixed)

<div style="position: absolute; margin-top: 20px;">Текст</div>
/* position: absolute, fixed исключают element из обычного flow
   маржины НЕ схлопываются */

8. Для float элементов

<div style="float: left; margin-top: 20px;">Текст</div>
/* float исключает элемент из обычного потока
   маржины НЕ схлопываются */

Практические примеры

Пример 1: Две строки текста

<p style="margin-bottom: 20px;">Первая строка</p>
<p style="margin-top: 30px;">Вторая строка</p>

Результат: расстояние = 30px (большее значение)

Пример 2: Блок внутри контейнера

<div style="margin-top: 20px;">  <!-- Родитель -->
  <h1 style="margin-top: 10px;">Заголовок</h1>  <!-- Ребёнок -->
</div>

Результат: итоговый margin-top = 20px (большее значение)

Пример 3: Flex контейнер (collapse НЕ происходит!)

<div style="display: flex; margin-top: 20px;">
  <p style="margin-top: 30px;">Абзац</p>
</div>

Результат: маржины НЕ схлопываются, потому что display: flex

Как избежать путаницы

Способ 1: Используй border или padding

.container {
  padding-top: 1px;  /* Блокирует collapse */
}

ребёнок {
  margin-top: 20px;  /* Теперь маржин не схлопывается */
}

Способ 2: Используй display: flex или grid

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

/* Маржины детей НЕ схлопываются */

Способ 3: Используй gap вместо margin

.container {
  display: flex;
  flex-direction: column;
  gap: 20px;  /* Расстояние между элементами, не collapse */
}

Способ 4: Контролируй маржины явно

.box + .box {
  margin-top: 20px;  /* Применяется только ко второму и далее */
}

Резюме

Margin collapse НЕ происходит, если:

  • Горизонтальные маржины (margin-left, margin-right)
  • У родителя есть border
  • У родителя есть padding
  • Элемент в контейнере display: flex, grid, inline-flex, inline-grid
  • Элемент позиционирован absolute или fixed
  • Элемент плавает (float)
  • Элемент inline или inline-block
  • У элемента overflow != visible

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