16 Модуль 4 Коробки и раскладка 15 мин урок 16 из 25

Блочная модель: из чего сделана каждая коробка

Почему элемент занимает больше места, чем ты задал, и как починить это одной строкой box-sizing.

Что ты научишься делать

  • Разберёшь элемент на четыре слоя: content, padding, border, margin
  • Поймёшь, почему 300px превращаются в 340px
  • Научишься чинить это одной строкой box-sizing

#Каждый элемент — коробка

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

СлойЧто этоВиден?
contentСамо содержимое: текст, картинкаДа
paddingВнутренний отступ между содержимым и рамкойКрасится фоном элемента
borderРамка вокруг paddingДа, если задана
marginВнешний отступ до соседейНет, всегда прозрачный

Блочная модель в разрезе

Четыре слоя коробки разлетаются по глубине, а ползунки меняют их размеры.

СлойЧто это
contentСамо содержимое: текст, картинка
paddingВнутренний отступ, красится фоном элемента
borderРамка вокруг padding
marginВнешний отступ, всегда прозрачный

#Главная ловушка: 300 превращается в 340

Ты задал карточке width: 300px. Добавил padding: 16px и border: 4px. Открыл — карточка занимает 340 пикселей.

Так работает значение по умолчанию: width задаёт ширину только содержимого. Отступы и рамка добавляются сверху.

CSSЧто на самом деле происходит
.card {  width: 300px;      /* ширина содержимого */  padding: 16px;     /* + 16 слева и 16 справа */  border: 4px solid; /* + 4 слева и 4 справа */}/* Итого на странице: 300 + 32 + 8 = 340px */

Пока карточка одна, это терпимо. Но как только ты ставишь три карточки по 33 % в ряд шириной 900px — они не помещаются, потому что каждая на самом деле шире, чем 300.

#Починка одной строкой

CSSПервые строки любого проекта
*, *::before, *::after {  box-sizing: border-box;}

border-box меняет смысл слова width: теперь оно означает ширину всей коробки вместе с отступами и рамкой. Задал 300 — получил 300, а содержимому осталось 300 − 32 − 8 = 260.

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

Так не надо

.col {
  width: 33.33%;
  padding: 16px;
}
/* три колонки не влезают в строку */

Проценты считаются от содержимого, а отступы добавляются сверху. Сумма получается больше 100 %, и третья колонка падает вниз.

Так надо

* { box-sizing: border-box; }

.col {
  width: 33.33%;
  padding: 16px;
}
/* ровно три в строку */

Теперь 33.33 % — это ширина всей колонки вместе с отступами. Три штуки дают ровно 100 %.

#Сокращённые записи

У padding и margin одинаковая логика записи. Количество значений определяет, к каким сторонам они относятся.

ЗаписьЗначение
padding: 16pxВсе четыре стороны
padding: 16px 24pxСверху и снизу 16, слева и справа 24
padding: 16px 24px 8pxСверху 16, по бокам 24, снизу 8
padding: 16px 24px 8px 12pxПо часовой стрелке: верх, право, низ, лево
padding-top: 16pxТолько одна сторона

#Схлопывание вертикальных отступов

Странность, которая сбивает с толку всех: у первого абзаца margin-bottom: 20px, у второго margin-top: 30px. Между ними будет не 50 пикселей, а 30.

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

Схлопывание в действии
В песочницу

Схлопывание отключается, если между отступами есть хоть что-то: рамка, внутренний отступ, или если родитель стал флекс- либо грид-контейнером. Именно поэтому во флекс-раскладке схлопывания нет — и почему многие просто задают отступы только в одну сторону.

#width, height и ограничители

Жёстко заданная высота — почти всегда ошибка: текста может оказаться больше, и он вылезет за пределы блока. Ширину тоже лучше ограничивать, а не фиксировать.

СвойствоЧто делаетКогда брать
widthЖёсткая ширинаРедко: иконки, аватарки
max-widthНе шире, но может быть ужеПочти всегда: контейнеры, картинки, текст
min-widthНе уже, но может быть ширеКнопки, ячейки таблиц
heightЖёсткая высотаПочти никогда
min-heightНе ниже, но может вырастиЭкранные блоки, карточки одинаковой высоты
CSSРезиновый контейнер — классика
.container {  /* до 1200px тянется, дальше стоит по центру */  max-width: 1200px;  margin: 0 auto;  padding: 0 24px;}/* Картинка никогда не вылезет за родителя */img {  max-width: 100%;  height: auto;}

Где спотыкаются почти все

Не задан box-sizing: border-box

Почему Все расчёты ширины ломаются: колонки не помещаются, сетка расползается. Причину найти сложно, потому что «я же написал 33 процента».

Как надо Первым правилом в файле: *, *::before, *::after { box-sizing: border-box; }

Отступы между блоками заданы с двух сторон

Почему Из-за схлопывания получается не то расстояние, которое ожидал, и в разных местах по-разному.

Как надо Договорись с собой: только margin-bottom. Или используй gap во флексах и гридах.

Жёсткая высота у блока с текстом

Почему Текст длиннее ожидаемого — и он вылезает за рамку или обрезается.

Как надо Бери min-height: блок не будет ниже заданного, но при необходимости вырастет.

Отступ у последнего элемента списка

Почему Снизу образуется лишний зазор, из-за которого блок выглядит несимметрично.

Как надо .item:last-child { margin-bottom: 0; } — или просто перейди на gap.

Блочная модель box model
Четыре слоя любого элемента: content, padding, border, margin.
Внутренний отступ padding
Расстояние от содержимого до рамки. Закрашивается фоном элемента.
Внешний отступ margin
Расстояние до соседних элементов. Всегда прозрачный.
box-sizing box-sizing
Определяет, входят ли padding и border в заданную ширину.
Схлопывание отступов margin collapsing
Соседние вертикальные margin объединяются в один, равный большему.

Проверь себя

  1. Элементу задано <code>width: 200px</code>, <code>padding: 20px</code>, <code>border: 5px</code>. Сколько он займёт при <code>box-sizing: content-box</code>?

    200 + 20·2 + 5·2 = 250. При <code>content-box</code> отступы и рамка добавляются к заданной ширине.

  2. Тот же элемент при <code>box-sizing: border-box</code> займёт…

    Теперь 200px — это вся коробка. Содержимому остаётся 200 − 40 − 10 = 150.

  3. У блока А снизу отступ 30px, у блока Б сверху 20px. Какое расстояние между ними?

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

  4. Какой слой блочной модели красится фоном элемента?

    Фон растекается под содержимое и внутренний отступ, до внешнего края рамки. Margin всегда прозрачный.

  5. Чем max-width лучше width для контейнера страницы?

    Жёсткий <code>width: 1200px</code> на телефоне вызовет горизонтальную прокрутку. <code>max-width</code> — нет.

Задание

Карточка товара с точными отступами

Свёрстай карточку по описанию:

  • включи box-sizing: border-box для всех элементов;
  • ширина карточки ровно 280px — вместе с отступами и рамкой;
  • внутренний отступ 20px со всех сторон;
  • рамка 2px;
  • скругление 14px;
  • у заголовка внутри — отступ снизу не меньше 8px, сверху нулевой.
Открыть в песочнице
    Подсказка 1

    Первое правило: *, *::before, *::after { box-sizing: border-box; }

    Подсказка 2

    Рамке нужен стиль и цвет, иначе её не будет видно: border: 2px solid #ddd;

    Подсказка 3

    Заголовку: .card__title { margin: 0 0 8px; }

    Показать решение
    HTMLindex.html
    <article class="card">  <h2 class="card__title">Раф на кокосовом</h2>  <p class="card__text">Мягкий, сладкий, без коровьего молока.</p>  <p class="card__price">240 ₽</p></article>
    CSSstyle.css
    *, *::before, *::after {  box-sizing: border-box;}.card {  width: 280px;  padding: 20px;  border: 2px solid #e0e0ea;  border-radius: 14px;  background: #fff;}.card__title {  margin: 0 0 8px;  font-size: 1.15rem;}.card__text {  margin: 0 0 12px;  color: #5b6070;  font-size: 0.9rem;}.card__price {  margin: 0;  font-weight: 700;}

    Проверь себя