width и height: задаём размеры и ловим побочные эффекты (CSS)

Когда ты ставишь width и height, кажется, что всё просто: «хочу блок 300 px — будет 300 px». На деле браузер считает размеры по правилам блочной модели, и появляются побочные эффекты: блок вылезает из сетки, ломается верстка, появляются скроллы. Разберём всё по шагам и с примерами, без теории ради теории.


Что именно задают width и height

По умолчанию width и height задают размер контентной области — то есть только того места, где лежит текст/картинка. В расчёт не входят:

  • padding (внутренние отступы),
  • border (рамка),
  • margin (внешние отступы).

Это критично, потому что итоговая ширина блока на экране почти всегда больше, чем значение width.

Пример:

css
.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)

Фиксированный размер. Удобно, когда нужен точный контроль.

css
.btn {
  width: 120px;
  height: 40px;
}

Минус: не масштабируется под разные экраны. На мобильных кнопка может быть слишком большой или слишком маленькой.

Проценты (%)

Размер считается от родителя.

css
.card {
  width: 50%;
}

Побочный эффект: если у родителя нет явно заданной ширины, процент может вести себя странно или вообще не работать так, как ты ожидаешь. Кроме того, при наличии padding и border в content-box ширина может превысить 100% родителя — и элемент вылезет за границы.

Единицы вьюпорта (vw, vh)

Относятся к размеру видимой области браузера.

css
.hero {
  width: 100vw;
  height: 80vh;
}

Подвох: 100vw шире, чем видимая область, если есть вертикальная полоса прокрутки — появляется горизонтальный скролл. Плюс при появлении скролла блок может «прыгать».

Относительные единицы (em, rem)

em зависит от font-size самого элемента или родителя, rem — от font-size корневого элемента (html).

css
.text-block {
  width: 30em;
}

Риск: при изменении размера шрифта ширина тоже меняется, и это может сломать сетку или вызвать неожиданные переносы.


Самый важный предохранитель: box-sizing

Чтобы не держать в голове, сколько пикселей прибавится от padding и border, почти везде используют:

css
* {
  box-sizing: border-box;
}

Теперь width включает в себя padding и border. То есть:

css
.box {
  width: 200px;
  padding: 20px;
  border: 5px solid red;
}

Реальная ширина блока — ровно 200 px. Контент внутри сожмётся, чтобы всё влезло.

Почему это спасает: ты можешь спокойно менять padding, не боясь, что блок станет шире и сломает сетку.


Побочные эффекты, которые реально ловят на практике

1. Горизонтальный скролл из‑за «лишних» пикселей

Частый кейс: сетка на процентах + padding + border при content-box.

css
.col {
  float: left;
  width: 33.333%;
  padding: 16px;
  border: 1px solid #ccc;
}

Итог: ширина колонки больше 33.333%, три колонки не влезают в строку, появляется горизонтальный скролл.

Решение:

css
* { box-sizing: border-box; }

или явно для колонок:

css
.col {
  box-sizing: border-box;
  width: 33.333%;
  padding: 16px;
  border: 1px solid #ccc;
}

2. Блок шире родителя из‑за width: 100% + padding

css
.inner {
  width: 100%;
  padding: 20px;
}

Без border-box итоговая ширина будет 100% + 40px, и блок вылезет за родителя.

Решение: box-sizing: border-box; или использовать width: calc(100% - 40px).


3. Скролл внутри элемента из‑за жёсткой height

css
.panel {
  height: 200px;
}

Если контента больше, чем помещается, появляется внутренний скролл (если не задано иное). Иногда это ожидаемо, иногда — нет.

Варианты:

  • разрешить скролл: .panel { height: 200px; overflow-y: auto; }
  • сделать высоту гибкой: .panel { min-height: 200px; } — блок будет не меньше 200 px, но может расти.

4. Картинки ломают верстку, если им задать width/height вручную

css
img {
  width: 100%;
  height: auto;
}

Правило: если задаёшь width, ставь height: auto, чтобы сохранить пропорции. Если задать оба значения жёстко, картинка исказится.


5. Инлайн‑элементы и width/height

Для элементов с display: inline (например, <span>) свойства width и height не работают.

css
span {
  width: 200px;   /* не сработает */
  height: 100px;  /* не сработает */
}

Решение: сделать элемент блочным или инлайн‑блочным:

css
span {
  display: inline-block;
  width: 200px;
  height: 100px;
}

Практические шаблоны под частые задачи

Фиксированный блок (карточка, кнопка)

css
.card {
  box-sizing: border-box;
  width: 300px;
  padding: 16px;
  border: 1px solid #ddd;
}

Блок будет ровно 300 px независимо от padding и border.


Резиновый блок на всю ширину родителя

css
.full-width {
  box-sizing: border-box;
  width: 100%;
  padding: 24px;
}

Не вылезет за родителя, даже с отступами.


Картинка на всю ширину контейнера

css
img {
  max-width: 100%;
  height: auto;
  display: block;
}

max-width вместо width защищает от ситуаций, когда картинка меньше контейнера: она не будет искусственно растягиваться.


Панель с минимальной высотой и скроллом

css
.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 в сетке → колонки не встают в строку.

Перед тем как сказать «верстка сломалась», проверь три вещи:

  1. box-sizing у элемента и у родителя.
  2. Есть ли padding и border и как они складываются.
  3. Какие единицы измерения ты использовал (%, 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).

Добавить комментарий