Когда ты ставишь width и height, кажется, что всё просто: «хочу блок 300 px — будет 300 px». На деле браузер считает размеры по правилам блочной модели, и появляются побочные эффекты: блок вылезает из сетки, ломается верстка, появляются скроллы. Разберём всё по шагам и с примерами, без теории ради теории.
Что именно задают width и height
По умолчанию width и height задают размер контентной области — то есть только того места, где лежит текст/картинка. В расчёт не входят:
padding(внутренние отступы),border(рамка),margin(внешние отступы).
Это критично, потому что итоговая ширина блока на экране почти всегда больше, чем значение width.
Пример:
.box { width: 200px; height: 100px; padding: 20px; border: 5px solid red; }
При box-sizing: content-box (это стандарт) реальный размер блока:
- ширина:
200 + 20 + 20 + 5 + 5 = 250px - высота:
100 + 20 + 20 + 5 + 5 = 150px
Если ты верстаешь сетку из колонок по 33.33% и добавляешь padding и border, колонки могут не влезть в строку — и появится горизонтальный скролл. Это самый частый побочный эффект.
Единицы измерения: какие брать и где они подводят
Пиксели (px)
Фиксированный размер. Удобно, когда нужен точный контроль.
.btn { width: 120px; height: 40px; }
Минус: не масштабируется под разные экраны. На мобильных кнопка может быть слишком большой или слишком маленькой.
Проценты (%)
Размер считается от родителя.
.card { width: 50%; }
Побочный эффект: если у родителя нет явно заданной ширины, процент может вести себя странно или вообще не работать так, как ты ожидаешь. Кроме того, при наличии padding и border в content-box ширина может превысить 100% родителя — и элемент вылезет за границы.
Единицы вьюпорта (vw, vh)
Относятся к размеру видимой области браузера.
.hero { width: 100vw; height: 80vh; }
Подвох: 100vw шире, чем видимая область, если есть вертикальная полоса прокрутки — появляется горизонтальный скролл. Плюс при появлении скролла блок может «прыгать».
Относительные единицы (em, rem)
em зависит от font-size самого элемента или родителя, rem — от font-size корневого элемента (html).
.text-block { width: 30em; }
Риск: при изменении размера шрифта ширина тоже меняется, и это может сломать сетку или вызвать неожиданные переносы.
Самый важный предохранитель: box-sizing
Чтобы не держать в голове, сколько пикселей прибавится от padding и border, почти везде используют:
* { box-sizing: border-box; }
Теперь width включает в себя padding и border. То есть:
.box { width: 200px; padding: 20px; border: 5px solid red; }
Реальная ширина блока — ровно 200 px. Контент внутри сожмётся, чтобы всё влезло.
Почему это спасает: ты можешь спокойно менять padding, не боясь, что блок станет шире и сломает сетку.
Побочные эффекты, которые реально ловят на практике
1. Горизонтальный скролл из‑за «лишних» пикселей
Частый кейс: сетка на процентах + padding + border при content-box.
.col { float: left; width: 33.333%; padding: 16px; border: 1px solid #ccc; }
Итог: ширина колонки больше 33.333%, три колонки не влезают в строку, появляется горизонтальный скролл.
Решение:
* { box-sizing: border-box; }
или явно для колонок:
.col { box-sizing: border-box; width: 33.333%; padding: 16px; border: 1px solid #ccc; }
2. Блок шире родителя из‑за width: 100% + padding
.inner { width: 100%; padding: 20px; }
Без border-box итоговая ширина будет 100% + 40px, и блок вылезет за родителя.
Решение: box-sizing: border-box; или использовать width: calc(100% - 40px).
3. Скролл внутри элемента из‑за жёсткой height
.panel { height: 200px; }
Если контента больше, чем помещается, появляется внутренний скролл (если не задано иное). Иногда это ожидаемо, иногда — нет.
Варианты:
- разрешить скролл:
.panel { height: 200px; overflow-y: auto; } - сделать высоту гибкой:
.panel { min-height: 200px; }— блок будет не меньше 200 px, но может расти.
4. Картинки ломают верстку, если им задать width/height вручную
img { width: 100%; height: auto; }
Правило: если задаёшь width, ставь height: auto, чтобы сохранить пропорции. Если задать оба значения жёстко, картинка исказится.
5. Инлайн‑элементы и width/height
Для элементов с display: inline (например, <span>) свойства width и height не работают.
span { width: 200px; /* не сработает */ height: 100px; /* не сработает */ }
Решение: сделать элемент блочным или инлайн‑блочным:
span { display: inline-block; width: 200px; height: 100px; }
Практические шаблоны под частые задачи
Фиксированный блок (карточка, кнопка)
.card { box-sizing: border-box; width: 300px; padding: 16px; border: 1px solid #ddd; }
Блок будет ровно 300 px независимо от padding и border.
Резиновый блок на всю ширину родителя
.full-width { box-sizing: border-box; width: 100%; padding: 24px; }
Не вылезет за родителя, даже с отступами.
Картинка на всю ширину контейнера
img { max-width: 100%; height: auto; display: block; }
max-width вместо width защищает от ситуаций, когда картинка меньше контейнера: она не будет искусственно растягиваться.
Панель с минимальной высотой и скроллом
.scroll-panel { min-height: 300px; max-height: 600px; overflow-y: auto; }
Панель не будет ниже 300 px и не вырастет выше 600 px; если контента больше — появится скролл.
Частые ошибки и быстрые проверки
- Жёсткая
width+paddingбезborder-box→ блок шире, чем ты думаешь. width: 100vw→ горизонтальный скролл из‑за полосы прокрутки.- Два фиксированных размера для картинки → искажение пропорций.
width/heightнаinline-элементе → ничего не происходит.- Неучтённый
borderв сетке → колонки не встают в строку.
Перед тем как сказать «верстка сломалась», проверь три вещи:
box-sizingу элемента и у родителя.- Есть ли
paddingиborderи как они складываются. - Какие единицы измерения ты использовал (
%,vw,emмогут вести себя не так, как кажется).
Полный пример: карточка в сетке
HTML:
<div class="grid"> <div class="card">Карточка 1</div> <div class="card">Карточка 2</div> <div class="card">Карточка 3</div> </div>
CSS:
* { box-sizing: border-box; } .grid { display: flex; gap: 16px; } .card { flex: 1; padding: 16px; border: 1px solid #ccc; background: #f9f9f9; }
![]()
Здесь flex: 1 даёт карточкам равную ширину, box-sizing: border-box гарантирует, что padding и border не сломают сетку, а gap отвечает за расстояние между карточками (вместо margin).
