Блочная модель

Блочная модель (box model) — фундаментальная концепция CSS, описывающая каждый элемент как прямоугольник из четырёх областей: content, padding, border и margin.

Зачем нужно

Каждый HTML-элемент — это прямоугольник. Блочная модель определяет, как рассчитываются его реальные размеры. Без понимания box model невозможно точно управлять отступами, границами и размерами элементов.

Где используется

  • Расчёт реальных размеров любого элемента
  • Управление внутренними и внешними отступами
  • Создание границ и рамок
  • Разрешение проблем с «неожиданной» шириной элементов

Предпосылки

Четыре области box model

┌──────────────── margin ─────────────────┐
│                                         │
│  ┌──────────── border ───────────────┐  │
│  │                                   │  │
│  │  ┌──────── padding ───────────┐   │  │
│  │  │                            │   │  │
│  │  │  ┌────── content ──────┐   │   │  │
│  │  │  │                     │   │   │  │
│  │  │  │   Текст / дети      │   │   │  │
│  │  │  │                     │   │   │  │
│  │  │  └─────────────────────┘   │   │  │
│  │  │                            │   │  │
│  │  └────────────────────────────┘   │  │
│  │                                   │  │
│  └───────────────────────────────────┘  │
│                                         │
└─────────────────────────────────────────┘

content — область содержимого

.box {
  width: 300px;   /* ширина content */
  height: 200px;  /* высота content */

  /* Ограничения */
  min-width: 200px;
  max-width: 500px;
  min-height: 100px;
  max-height: 400px;
}

padding — внутренний отступ

Пространство между содержимым и границей. Фон элемента распространяется на padding.

.box {
  /* Все стороны */
  padding: 20px;

  /* Вертикаль | Горизонталь */
  padding: 10px 20px;

  /* Верх | Горизонталь | Низ */
  padding: 10px 20px 30px;

  /* Верх | Право | Низ | Лево (по часовой) */
  padding: 10px 20px 30px 40px;

  /* Отдельные стороны */
  padding-top: 10px;
  padding-right: 20px;
  padding-bottom: 30px;
  padding-left: 40px;

  /* Логические свойства */
  padding-block: 10px 30px;   /* верх и низ */
  padding-inline: 20px 40px;  /* лево и право */
}

border — граница

.box {
  /* Сокращённая запись: ширина | стиль | цвет */
  border: 2px solid #333;

  /* Отдельные стороны */
  border-top: 1px dashed red;
  border-bottom: 3px double blue;

  /* Отдельные свойства */
  border-width: 1px 2px 3px 4px;
  border-style: solid;
  border-color: #333;

  /* Скругление углов */
  border-radius: 8px;
  border-radius: 50%; /* круг (если width = height) */
  border-radius: 10px 20px 30px 40px; /* каждый угол */

  /* Логические свойства */
  border-block: 1px solid #ddd;
  border-inline-start: 4px solid blue;
}

Стили границ:

.borders {
  border-style: solid;   /* сплошная линия */
  border-style: dashed;  /* штрихи */
  border-style: dotted;  /* точки */
  border-style: double;  /* двойная */
  border-style: groove;  /* объёмная вдавленная */
  border-style: ridge;   /* объёмная выпуклая */
  border-style: inset;   /* вдавленная рамка */
  border-style: outset;  /* выпуклая рамка */
  border-style: none;    /* без границы */
}

margin — внешний отступ

Пространство снаружи границы. Фон НЕ распространяется на margin.

.box {
  /* Все стороны */
  margin: 20px;

  /* Центрирование блока по горизонтали */
  margin: 0 auto;

  /* Отдельные стороны */
  margin-top: 20px;
  margin-bottom: 30px;

  /* Отрицательные отступы — элемент сдвигается */
  margin-top: -10px;
  margin-left: -20px;

  /* Логические свойства */
  margin-block: 20px;
  margin-inline: auto; /* центрирование */
}

box-sizing — как считать размеры

content-box (по умолчанию)

width/height задают размер только content. Padding и border добавляются сверху.

.box-content {
  box-sizing: content-box;
  width: 300px;
  padding: 20px;
  border: 2px solid black;
  /* Реальная ширина = 300 + 20*2 + 2*2 = 344px */
}

border-box (рекомендуемый)

width/height включают content + padding + border. Размер предсказуемый.

.box-border {
  box-sizing: border-box;
  width: 300px;
  padding: 20px;
  border: 2px solid black;
  /* Реальная ширина = 300px (content сжимается до 256px) */
}

Глобальный сброс (обязательная практика)

/* Включить border-box для ВСЕХ элементов */
*,
*::before,
*::after {
  box-sizing: border-box;
}

Практически все современные проекты используют border-box глобально. Это первое правило в любом CSS-файле.

Схлопывание margin (margin collapsing)

Вертикальные margin соседних блочных элементов объединяются — берётся больший из двух:

.block-a {
  margin-bottom: 30px;
}

.block-b {
  margin-top: 20px;
}

/* Расстояние между ними = 30px (не 50px!) */
/* Берётся больший margin */

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

  1. Соседние элементы — вертикальные margin смежных блоков
  2. Родитель и первый/последний ребёнок — если нет padding, border или содержимого между ними
  3. Пустой блок — его собственные margin-top и margin-bottom схлопываются
/* Проблема: margin ребёнка "выпадает" из родителя */
.parent {
  background: lightblue;
  /* margin-top ребёнка "выпадет" наружу */
}
.child {
  margin-top: 50px; /* Сдвинет .parent вниз! */
}

/* Решения: */
.parent {
  /* Вариант 1: padding */
  padding-top: 1px;

  /* Вариант 2: border */
  border-top: 1px solid transparent;

  /* Вариант 3: overflow */
  overflow: hidden;

  /* Вариант 4: display: flow-root */
  display: flow-root;
}

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

  • Элементы с float
  • Элементы с position: absolute/fixed
  • Flex-элементы и grid-элементы
  • Элементы с overflow отличным от visible
  • Горизонтальные margin (только вертикальные схлопываются)

outline — не часть box model

.box {
  /* outline НЕ занимает место, НЕ влияет на размеры */
  outline: 2px solid blue;
  outline-offset: 4px; /* отступ от border */
}

/* Используется для фокуса */
button:focus {
  outline: 2px solid #007bff;
  outline-offset: 2px;
}

/* Никогда не убирайте outline без замены! */
button:focus {
  outline: none; /* Плохо для доступности */
}
button:focus-visible {
  outline: 2px solid #007bff; /* Хорошо — только для клавиатуры */
}

display и box model

/* Block — занимает всю ширину, можно задать width/height/margin */
.block { display: block; }

/* Inline — ширина по содержимому, вертикальные margin/padding
   НЕ влияют на поток */
.inline { display: inline; }

/* Inline-block — inline снаружи, block внутри
   Можно задать width/height/margin */
.inline-block { display: inline-block; }

Просмотр box model в DevTools

В Chrome DevTools:

  1. Правый клик на элемент → «Inspect»
  2. Вкладка «Computed» показывает box model визуально
  3. Наведение на элемент подсвечивает: content (синий), padding (зелёный), border (жёлтый), margin (оранжевый)

Частые ошибки

  1. Забыли box-sizing: border-box — элемент шире ожидаемого:
    /* ОШИБКА */
    .col { width: 50%; padding: 20px; }
    /* Реальная ширина = 50% + 40px → выходит за контейнер */
    
  2. Margin на inline-элементах — вертикальные отступы не работают:
    /* НЕ сработает */
    span { margin-top: 20px; }
    /* Нужен display: inline-block или block */
    
  3. Неожиданное схлопывание margin — особенно «выпадение» margin ребёнка из родителя
  4. Удаление outline при фокусе — нарушает доступность для клавиатурной навигации

Практика

  • Создать элемент и посмотреть box model в DevTools
  • Сравнить content-box и border-box на элементе с padding
  • Воспроизвести схлопывание margin и исправить через display: flow-root
  • Центрировать блок через margin: 0 auto
  • Добавить box-sizing: border-box глобально и проверить результат

Связанные темы

Ресурсы