CSS box-sizing и блочная модель: как работает border-box на практике

CSS box-sizing и блочная модель: как работает border-box на практике

CSS box-sizing и блочная модель: как работает border-box на практике

Если вы когда-либо удивлялись, почему блок с шириной 300px внезапно «распух» после добавления padding и border — вам нужен CSS box-sizing: border-box. Это базовая, но критически важная тема блочной модели (CSS Box Model), которая экономит часы отладки и делает вёрстку предсказуемой.

Что такое блочная модель CSS (Box Model)?

Каждый элемент в браузере — это «коробка» из четырёх слоёв: content → padding → border → margin. Ширина и высота элемента зависят от того, учитываются ли padding и border внутри заданной ширины/высоты или прибавляются сверху.

  • content — содержимое (текст, изображения).
  • padding — внутренние отступы между контентом и рамкой.
  • border — рамка вокруг элемента.
  • margin — внешние отступы (не входят в размер коробки).
  • box-sizing: content-box vs border-box

    По умолчанию большинство элементов используют content-box. Это означает: если вы задали width: 300px, то реальная занимаемая ширина будет 300 + padding-left + padding-right + border-left + border-right. В border-box всё наоборот: padding и border входят внутрь заданных 300px — поэтому итоговый размер остаётся ровно 300px.

    .demo {
      width: 300px;
      padding: 20px;
      border: 2px solid #4a90e2;
    }
    
    .content-box { box-sizing: content-box; background: #eaf3ff; }
    .border-box  { box-sizing: border-box;  background: #d8f7e1; }
    
    <div class="demo content-box">content-box: фактическая ширина 344px (300 + 20 + 20 + 2 + 2)</div>
    <div class="demo border-box">border-box: фактическая ширина 300px</div>
    

    Почему border-box «победил» в реальных проектах

  • Проще считать: указали ширину — получили именно её, без сюрпризов.
  • Сетки не «ломаются» при добавлении padding/border.
  • Меньше переполнений (overflow) и горизонтальных скроллов на мобильных.
  • Глобальный reset box-sizing: два надёжных варианта

    Чаще всего проект начинают с глобального reset, чтобы все элементы и псевдоэлементы считали размеры по border-box. Есть два популярных способа.

    Вариант 1: простой и понятный

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

    Плюсы: минимализм и предсказуемость. Минусы: иногда неудобно переопределять отдельные компоненты под content-box (если это вдруг нужно).

    Вариант 2: наследование от html

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

    Преимущество — гибкость. Можно локально задать container { box-sizing: content-box; } и все внутренние элементы легко переключатся на другую модель, если им прописать inherit.

    Практика: частые задачи и решения

    1) Ширина 100% с отступами без переполнения

    Задача: сделать блок на всю ширину контейнера, но с приятным внутренним отступом. С content-box элемент может «вылезти» наружу. С border-box всё ровно.

    .full {
      width: 100%;
      padding: 16px;
      box-sizing: border-box;
      background: #fffbe6;
      border: 1px solid #f0d264;
    }
    

    2) Карточки в ряд с равными отступами

    Сетки часто делают на Flex или Grid. C border-box внутренние отступы карточки не ломают раскладку, а gap отвечает за промежутки между карточками.

    .cards {
      display: flex;
      gap: 16px; /* поддерживается современными браузерами */
    }
    .card {
      flex: 1 1 calc(33.333% - 10.67px); /* для примера, или просто flex: 1 */
      padding: 16px;
      border: 1px solid #ddd;
      box-sizing: border-box;
      background: #fafafa;
    }
    

    Совет: если можно, используйте просто flex: 1 и задайте минимальные ширины через min-width. А внешние отступы — через gap, а не margin между карточками.

    3) Формы и поля ввода

    Инпуты с content-box «расползаются» при увеличении padding. Переключите их на border-box для стабильной ширины и красивых отступов внутри.

    input, select, textarea {
      width: 100%;
      padding: 12px 16px;
      border: 1px solid #cfd8dc;
      border-radius: 6px;
      box-sizing: border-box;
    }
    

    4) Компонентная настройка: когда нужен content-box

    Редко, но бывает, что компонент полагается на content-box (например, сложный калькулятор размеров или анимация ширины контента без учёта рамок). Тогда локально переключаемся:

    .widget {
      box-sizing: content-box; /* локальное исключение */
    }
    .widget__inner {
      width: 320px; /* теперь это только content */
      padding: 20px;
      border: 2px solid #333;
    }
    

    Как считать размеры: простые формулы

  • content-box: итоговая ширина = width + padding-left + padding-right + border-left + border-right
  • border-box: итоговая ширина = width (padding и border уже внутри)
  • Пример: width: 300px; padding: 20px; border: 2px. В content-box итог — 344px; в border-box — 300px. То же применимо к высоте.

    Отладка в DevTools

    Откройте вкладку Elements → Layout/Computed. Там есть визуальная схема box model. Наведите на элемент — увидите размеры content, padding, border и margin, а также увидите, не идёт ли переполнение по ширине/высоте.

    Margin collapsing: важная особенность отступов

    С схлопыванием внешних отступов (margin collapsing) часто путаются. Оно не связано с box-sizing, но влияет на итоговый отступ между блоками. Верхний margin дочернего блока может «слиться» с верхним margin родителя, образуя один суммарный отступ. Чтобы избежать, можно, например, добавить родителю padding-top, border-top или overflow: auto.

    .parent {
      /* padding или border сверху предотвратит схлопывание */
      padding-top: 1px; 
      background: #f7f7f7;
    }
    .child {
      margin-top: 20px; /* без padding у родителя может схлопнуться */
    }
    

    Частые ошибки и полезные советы

  • Дублирование reset. Если подключаете CSS-фреймворк или normalize/reset, проверьте, не задаётся ли уже border-box глобально, чтобы не конфликтовать.
  • outline не влияет на размер. В отличие от border, outline не участвует в расчёте ширины/высоты — удобно для hover/focus-состояний без «дёрганий» макета.
  • min/max-width и высота. В border-box эти ограничения включают padding и border — учитывайте это в расчётах адаптивных карточек и модалок.
  • Изображения и заменяемые элементы. box-sizing к ним применим, но не забывайте про их собственные особенности рендеринга (например, у img лучше добавить max-width: 100%; height: auto).
  • Транзиции размеров. Анимировать width/height проще и предсказуемее, если padding/border уже внутри (border-box).
  • Мини‑практикум: адаптивная «шапка» с поиском

    Соберём простую строку: логотип, поиск и кнопка. Благодаря border-box поиск растягивается ровно на доступное место и не уезжает при увеличении внутренних отступов.

    /* Глобально */
    html { box-sizing: border-box; }
    *, *::before, *::after { box-sizing: inherit; }
    
    .header {
      display: flex;
      align-items: center;
      gap: 12px;
      padding: 12px 16px;
      border-bottom: 1px solid #e0e0e0;
    }
    .logo { flex: 0 0 auto; }
    .search {
      flex: 1 1 auto;
      display: flex;
    }
    .search input {
      flex: 1 1 auto;
      padding: 10px 14px;
      border: 1px solid #cfd8dc;
      border-radius: 6px;
      box-sizing: border-box; /* избыточно, но явно */
    }
    .btn {
      flex: 0 0 auto;
      padding: 10px 14px;
      border: 1px solid #1976d2;
      background: #2196f3;
      color: #fff;
      border-radius: 6px;
    }
    
    <header class="header">
      <div class="logo">Лого</div>
      <div class="search">
        <input type="search" placeholder="Найдите статью…">
      </div>
      <button class="btn">Войти</button>
    </header>
    

    Итоги

    Используйте box-sizing: border-box по умолчанию для всего проекта — и вы получите стабильные сетки, предсказуемые размеры и меньше багов при доработках. Локально переключайтесь на content-box только когда это осознанно необходимо. Отлаживайте размеры через DevTools и не забывайте про схлопывание margin — это частый источник недоразумений у новичков.

    Хотите быстрее прокачать практику вёрстки с нуля до уверенного уровня? Загляните на интенсив: Прокачать вёрстку на интенсиве «Вёрстка сайта с нуля 2.0» — много практики, разбор типичных ошибок и современные приёмы CSS.

    Источник

    НЕТ КОММЕНТАРИЕВ

    Оставить комментарий