Почему блок шире, чем вы задали, и откуда взялся лишний отступ
box-sizing: border-box и объяснять зачемКаждый элемент на странице — прямоугольник из четырёх слоёв, от центра наружу:
| Слой | Свойство | Что это |
|---|---|---|
| Содержимое | width, height | Текст, картинка, вложенные элементы |
| Внутренний отступ | padding | Расстояние от содержимого до рамки; закрашивается фоном блока |
| Рамка | border | Толщина, стиль, цвет: 1px solid #ddd |
| Внешний отступ | margin | Расстояние до соседей; всегда прозрачен |
Отступы записывают по сторонам (padding-top, margin-left…) или сокращённо по часовой стрелке от верха: margin: 10px 20px 30px 40px — верх, право, низ, лево; margin: 10px 20px — верх-низ и лево-право; margin: 10px — все стороны.
В инструментах разработчика (F12 → Elements → вкладка Computed) у выбранного элемента нарисована схема этих четырёх слоёв с размерами — первый инструмент, когда «что-то съехало».
По умолчанию width задаёт ширину только содержимого. Отступы и рамка добавляются сверху. Серая полоса в примере — ровно 300px:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Блочная модель</title>
<style>
body { font-family: Arial, sans-serif; }
.ruler { width: 300px; height: 10px; background: #999; }
.box {
width: 300px;
padding: 20px;
border: 5px solid #1967d2;
margin: 10px 0;
background: #eef3fb;
}
.border-box { box-sizing: border-box; }
</style>
</head>
<body>
<div class="ruler"></div>
<div class="box">width: 300px — блок шире линейки</div>
<div class="box border-box">width: 300px и box-sizing: border-box</div>
</body>
</html>

Первый блок занимает 300 + 2 × 20 + 2 × 5 = 350px. С box-sizing: border-box width означает ширину вместе с отступами и рамкой — блок занимает ровно 300px, а на содержимое остаётся 250px. Так считать проще, поэтому почти каждый файл стилей начинается со строки, включающей это для всех элементов:
*, *::before, *::after { box-sizing: border-box; }
Свойство display определяет, как элемент встаёт среди соседей:
| display | Поведение | Элементы по умолчанию |
|---|---|---|
block | С новой строки, на всю ширину родителя; width, height, все отступы работают | div, p, h1–h6, ul, section, header |
inline | В строке текста; width и height не действуют, вертикальные margin не раздвигают строки | span, a, strong, em |
inline-block | В строке, но с размерами и отступами, как у блока | button, input, img ведёт себя похоже |
none | Элемент не отображается и не занимает места | — |
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>display</title>
<style>
body { font-family: Arial, sans-serif; }
span, div.b {
width: 120px;
padding: 4px;
margin: 6px;
border: 2px solid #c62828;
}
.ib { display: inline-block; }
</style>
</head>
<body>
<div class="b">div — блок</div>
<div class="b">div — блок</div>
<p>Текст <span>span — строчный</span> и <span>ещё span</span>: ширина не действует.</p>
<p>Текст <span class="ib">inline-block</span> и <span class="ib">inline-block</span> — ширина действует.</p>
</body>
</html>

Ширина 120px сработала у блоков div и у inline-block, но не у обычного span. display меняет только поведение, не смысл: ссылка с display: block остаётся ссылкой. В модулях 06 и 07 появятся ещё два значения — flex и grid.
Вертикальные внешние отступы соседних блоков не складываются, а схлопываются: остаётся больший из двух.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Схлопывание отступов</title>
<style>
body { font-family: Arial, sans-serif; }
.a, .b { margin: 20px 0; padding: 6px; background: #fff3e0; border: 1px solid #ef6c00; }
</style>
</head>
<body>
<div class="a">margin-bottom: 20px</div>
<div class="b">margin-top: 20px — между блоками 20px, а не 40px</div>
</body>
</html>

Так задумано для текста: абзацы с margin: 1em 0 стоят на расстоянии 1em, а не 2em. Горизонтальные отступы не схлопываются никогда. Отступ первого вложенного элемента может «вытечь» наружу родителя — заголовок h1 с верхним отступом сдвигает вниз весь блок, в котором лежит. Лечится padding у родителя или раскладкой flex/grid (у их элементов отступы не схлопываются).
Классический приём для основной колонки сайта: ограничить ширину max-width и поставить margin слева и справа в auto — браузер поделит свободное место поровну.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Центрирование</title>
<style>
body { font-family: Arial, sans-serif; margin: 0; background: #eceff1; }
.container {
max-width: 360px;
margin: 16px auto;
padding: 16px;
background: white;
}
</style>
</head>
<body>
<div class="container">
Колонка текста шириной не больше 360px по центру окна.
На узком экране она занимает всю ширину.
</div>
</body>
</html>


max-width вместо width — ключ к адаптивности: на широком экране колонка не шире 360px, на узком сжимается до ширины окна, и горизонтальной прокрутки нет. Длина строки текста для удобного чтения — 60–80 символов, поэтому колонку статьи ограничивают примерно max-width: 70ch (ch — ширина символа «0»).
Если задать блоку фиксированную высоту, а содержимое окажется больше, оно вылезет за границы: по умолчанию overflow: visible.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Переполнение</title>
<style>
body { font-family: Arial, sans-serif; }
.note { width: 260px; height: 32px; border: 2px solid #6a1b9a; margin-bottom: 64px; }
.scroll { overflow: auto; }
</style>
</head>
<body>
<div class="note">Текст длиннее, чем помещается в блок высотой 32px, вылезает за рамку и налезает на соседей.</div>
<div class="note scroll">С overflow: auto у блока появляется своя прокрутка, и текст остаётся внутри рамки.</div>
</body>
</html>

overflow: auto — прокрутка, когда нужно; hidden — обрезать. Лучшее решение чаще всего — не задавать height вовсе: блок вырастет по содержимому. Текст на кнопках и в карточках бывает длиннее, чем на макете — переводы, длинные фамилии, крупный шрифт у пользователя, — поэтому верстают с запасом.
Всё из модуля в одном компоненте: border-box, ограничение ширины, отступы, скругление border-radius, тень box-shadow (смещение по x, по y, размытие, цвет), обнулённые отступы заголовка и абзаца внутри карточки:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Карточка</title>
<style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; padding: 16px; font-family: Arial, sans-serif; background: #f5f5f5; }
.card {
max-width: 320px;
padding: 16px 20px;
background: white;
border: 1px solid #ddd;
border-radius: 12px;
box-shadow: 0 2px 6px rgb(0 0 0 / 12%);
}
.card h1 { margin: 0 0 8px; font-size: 1.25rem; }
.card p { margin: 0 0 12px; color: #555; }
.card .price { font-weight: bold; color: #1967d2; }
</style>
</head>
<body>
<article class="card">
<h1>Раф с лавандой</h1>
<p>Эспрессо, сливки и лавандовый сироп.</p>
<span class="price">290 ₽</span>
</article>
</body>
</html>

*, *::before, *::after { box-sizing: border-box; }body { margin: 0; } — у body по умолчанию отступ 8px.img { max-width: 100%; height: auto; } — картинка не шире своего блока.line-height: 1.5) — у body.padding + border + marginbox-sizing: border-box — width включает отступы и рамку; ставят всем элементамblock — на всю ширину, inline — без размеров, inline-block — в строке с размерамиmargin соседей схлопываются до большегоmax-width + margin: 0 autoheight — источник переполнения; пусть блок растёт по содержимому