Урок 04

Box model: margin, padding, border

Что такое box model

Box model — модель, по которой браузер рассчитывает размеры каждого элемента.

Уровни (снаружи внутрь):

margin → border → padding → content

Что означает:

  • content — само содержимое (текст, картинка).
  • padding — внутренние отступы (между содержимым и рамкой).
  • border — рамка.
  • margin — внешние отступы (между элементами).

content-box vs border-box

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

.box {
    width: 200px;
    padding: 20px;
    border: 2px solid black;
    /* итоговая ширина: 200 + 40 + 4 = 244px */
}

border-box:

*, *::before, *::after {
    box-sizing: border-box;
}

.box {
    width: 200px;
    padding: 20px;
    border: 2px solid black;
    /* итоговая ширина: 200px (padding и border внутри) */
}

Правило: всегда border-box. Это стандарт.

padding

Со всех сторон:

padding: 16px;

Вертикаль / горизонталь:

padding: 16px 24px;   /* top-bottom 16, left-right 24 */

Сверху / горизонталь / снизу:

padding: 8px 16px 24px;

Все четыре:

padding: 8px 16px 24px 32px;   /* top right bottom left (по часовой) */

Отдельно:

padding-top: 16px;
padding-right: 24px;
padding-bottom: 16px;
padding-left: 24px;

Правило: padding не может быть отрицательным.

margin

Синтаксис такой же:

margin: 16px;
margin: 8px 16px;
margin: 8px 16px 24px;
margin: 8px 16px 24px 32px;

Отдельно:

margin-top: 16px;
margin-inline: 24px;   /* left + right (логические свойства) */
margin-block: 16px;    /* top + bottom */

Отрицательные:

margin-top: -8px;   /* ок */

Правило: margin может быть отрицательным.

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

Вертикальные margin соседних блоков схлопываются:

<p style="margin-bottom: 20px">Первый</p>
<p style="margin-top: 30px">Второй</p>

Отступ между ними: не 50px, а 30px (максимум из двух).

Когда схлопываются:

  • Соседние вертикальные margin.
  • Родителя и первого ребёнка (если нет padding/border между ними).
  • Родителя и последнего ребёнка.

Как избежать:

.parent {
    padding-top: 1px;     /* или */
    border-top: 1px solid transparent;   /* или */
    overflow: hidden;     /* создаст BFC */
    display: flow-root;   /* современный способ */
}

Правило: используйте gap во flex/grid вместо margin — нет схлопывания.

margin и padding: когда что

padding — внутри:

  • Отступ от текста до рамки.
  • Кнопки, карточки.

margin — снаружи:

  • Расстояние между элементами.
  • Отступ секции.

Правило: внутри — padding. Снаружи — margin (или gap).

border

border: 1px solid #e5e5e5;

/* Отдельно */
border-width: 1px;
border-style: solid;
border-color: #e5e5e5;

/* Сторона */
border-top: 2px dashed red;
border-bottom: 1px solid #000;

Стили:

  • solid — сплошная.
  • dashed — пунктир.
  • dotted — точки.
  • double — двойная.
  • none — нет.

Правило: border: 1px solid — дефолт. Для акцента — 2px.

border-radius

border-radius: 8px;
border-radius: 50%;            /* круг */
border-radius: 8px 0 8px 0;    /* углы по часовой */
border-radius: 999px;          /* пилюля */

Правило: 4-8px для современного вида. 50% — для круглых аватаров.

outline

outline: 2px solid blue;
outline-offset: 2px;

Отличие от border:

  • Не занимает места в box model.
  • Не влияет на layout.
  • Не скругляется с border-radius (в старых браузерах).

Правило: outline — для фокуса. Не убирать!

:focus-visible {
    outline: 2px solid #c1442e;
    outline-offset: 2px;
}

box-shadow

box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
/* x y blur spread color */

box-shadow: 0 1px 2px #000;                  /* маленькая */
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);  /* средняя */
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15); /* большая */

/* Внутренняя */
box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);

/* Несколько теней */
box-shadow:
    0 1px 2px rgba(0,0,0,0.05),
    0 4px 8px rgba(0,0,0,0.05);

Правило: тень — мягкая, многослойная, полупрозрачная.

Логические свойства

Вместо margin-top — margin-block-start:

margin-block-start: 16px;   /* top или bottom в RTL */
margin-inline-end: 24px;    /* right или left в RTL */
padding-block: 8px 16px;    /* top / bottom */
padding-inline: 16px 24px;  /* left / right */

Что даёт: работает для RTL-языков (арабский, иврит).

Правило: использовать для международных проектов.

Сброс стилей

*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

Что даёт: убирает дефолтные отступы браузера.

Пример: карточка

.card {
    box-sizing: border-box;
    padding: 24px;
    margin-bottom: 16px;
    background: #fff;
    border: 1px solid #e5e5e5;
    border-radius: 10px;
    box-shadow: 0 1px 2px rgba(0,0,0,0.05);
}

.card:hover {
    border-color: #c1442e;
    box-shadow: 0 4px 16px rgba(0,0,0,0.08);
}

.card__title {
    margin: 0 0 8px;
    font-size: 1.25rem;
}

.card__text {
    margin: 0;
    color: #6b6b6b;
}

Практика

1. Создайте карточку с padding, border, radius, shadow.

2. Попробуйте border-box vs content-box — проверьте ширину.

3. Схлопывание margin:

<div style="margin-bottom: 20px">A</div>
<div style="margin-top: 30px">B</div>

Проверьте в DevTools — расстояние 30px.

4. Кнопка с padding, border, radius, hover.

5. Фокус через :focus-visible.

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

1. content-box по умолчанию:

Ширина не такая, как ожидалось

Решение: box-sizing: border-box.

2. margin: 0 auto для центрирования блока:

Работает, но требует width меньше 100%.

Решение: flex/grid.

3. Схлопывание margin:

Ожидал 50px, получил 30px

Решение: gap или flow-root.

4. outline: none:

Не видно фокуса

Решение: :focus-visible.

5. border добавляет ширину:

1200px + border = 1204px

Решение: border-box.

6. padding для вертикального выравнивания:

Хрупко

Решение: flex align-items: center.

7. Огромный margin сверху у первого элемента:

Схлопывание с body

Решение: padding у родителя.

8. box-shadow без rgba:

box-shadow: 0 2px 8px #000;   /* жёстко */

Решение: rgba(0,0,0,0.1).

Итог

  • Box model: margin → border → padding → content.
  • border-box — всегда.
  • padding — внутри, margin — снаружи.
  • Схлопывание margin — вертикальное.
  • border: 1px solid — дефолт.
  • border-radius — 4-8px или 999px.
  • box-shadow — мягкая, rgba.
  • outline — для фокуса, не убирать.
  • Логические свойства — для RTL.

Дальше — display, position, z-index.