Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Властивість CSS box-sizing». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`box-sizing`** визначає як розраховується `width` і `height` елемента в CSS. `content-box` (дефолт) додає padding і border поверх зазначеної ширини. `border-box` залишає зазначену ширину кінцевим розміром. ```css *, *::before, *::after { box-sizing: border-box; /* стандартний reset у галузі */ } ``` **Головне:** при `border-box` `width: 200px` завжди дає 200px, незалежно від padding і border.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`box-sizing`** визначає, чи включає зазначена `width` і `height` елемента тільки вміст, чи ще й padding та border. ## Теорія ### TL;DR - `content-box` (браузерний дефолт): `width: 200px` + `padding: 20px` = реальних 240px. Padding додається зовні. - `border-box`: `width: 200px` - це кінцевий розмір. Padding "вирізається" зсередини. - Аналогія: content-box - замовляєш піцу на 200px, але начинка виходить за краї; border-box - коробка рівно 200px, де все поміщається всередині. - Правило вибору: використовуй `border-box` скрізь через `* { box-sizing: border-box; }`. Саме так роблять Bootstrap, Tailwind і React-проекти за замовчуванням. ### Швидкий приклад ```css .content-box { box-sizing: content-box; /* дефолт браузера */ width: 200px; padding: 20px; border: 5px solid; /* реальна ширина: 200 + 40 + 10 = 250px */ } .border-box { box-sizing: border-box; width: 200px; padding: 20px; border: 5px solid; /* реальна ширина: 200px, область вмісту = 150px */ } ``` Перший блок займає 250px. Другий - рівно 200px. Однакові значення CSS, різні моделі розрахунку розміру. ### Головна різниця Браузери за замовчуванням використовують `content-box` згідно зі специфікацією CSS2.1. Тому `width: 200px; padding: 20px` дає елемент шириною 240px. Більшість розробників очікують протилежного - звідси горизонтальний скрол на мобільних, який роками очолює рейтинг CSS-багів на StackOverflow. `border-box` вирішує це: число яке ти пишеш - це число яке отримуєш. ### Коли що використовувати - Фіксовані UI-компоненти (картки, модалки, кнопки) - `border-box`, щоб padding не ламав лейаут. - Дочірні елементи flex або grid - `border-box`, запобігає переповненню контейнера. - Текстові блоки де розмір диктує вміст - тут `content-box` підходить, але `border-box` теж не завадить. - Глобальний reset - `border-box` через `*` є стандартом галузі. Стаття Пола Айріша 2012 року показала, що це миттєво фіксує більшість padding-багів у лейауті. ### Таблиця порівняння | | content-box | border-box | |---|---|---| | Що означає `width` | тільки область вмісту | загальний зовнішній розмір | | Дефолт браузера | Так (CSS2.1) | Ні | | Розмір вмісту | дорівнює `width` | `width - padding - border` | | Коли використовувати | чисто контентний розмір (рідко) | 99% лейаутів | ### Як браузер це розраховує CSS-рушії Blink (Chrome) і Gecko (Firefox) читають `box-sizing` на етапі вирішення стилів. Для `border-box` рушій віднімає `padding + border` від зазначеної ширини перед тим як призначити ширину вмісту. Для `content-box` цей крок пропускається. Все це відбувається на фазі лейауту, до малювання, відповідно до розділу 10.2 специфікації CSS2.1. ### Типові помилки **Забувають про браузерний дефолт.** Пишеш `width: 300px; padding: 24px` і дивуєшся чому картка виходить за межі контейнера. Реальна ширина - 348px, а не 300px. Рішення: додай глобальний reset у стилі проекту. ```css /* Стандартний глобальний reset */ *, *::before, *::after { box-sizing: border-box; } ``` **Мікс box-sizing у flexbox.** Один дочірній елемент використовує `content-box`, інший `border-box`. Лейаут ламається, бо flex рахує зовнішні розміри. Задай `box-sizing` на контейнері та дозволь дочірнім успадкувати. ```css .flex-container { display: flex; box-sizing: border-box; /* дочірні успадковують */ } .flex-child { flex: 1; padding: 20px; /* залишається в межах flex-треку, без overflow */ } ``` **`border-box` на елементах `img`.** Зображення зазвичай не мають padding чи border. Налаштування не спричиняє багів, але зменшить простір для вмісту якщо пізніше додати padding. Краще пропустити або явно вказати `content-box` для зображень. **Забувають про псевдоелементи.** `::before` і `::after` не успадковують `box-sizing` автоматично в старих reset-стилях. Тому сучасний патерн явно включає `*::before, *::after`. ### Де зустрічається в реальних проектах - React (create-react-app, Vite) - `* { box-sizing: border-box; }` в `index.css` за замовчуванням. - Tailwind CSS - застосовує `border-box` на `html` і `body` через preflight reset. - Bootstrap 5 - універсальний `border-box` для стабільності grid. - Next.js - глобальний reset включає його щоб уникнути hydration-розбіжностей. - Material UI - картки і кнопки використовують `border-box` для відповідності дизайн-токенам. ### Питання на співбесіді **Q:** Який браузерний дефолт для `box-sizing` і чому це важливо? **A:** `content-box`, успадкований з CSS2.1. Без reset кожен елемент з padding стає ширшим за зазначену ширину. Такі баги складно відстежити без знання цього дефолту. **Q:** Як `box-sizing` взаємодіє з `min-width` і `max-width`? **A:** Ті ж правила. При `border-box` `min-width: 200px` означає що загальний зовнішній розмір - щонайменше 200px. Padding і border все одно вираховуються зі вмісту всередині. **Q:** Чи впливає `box-sizing` на `::before` і `::after`? **A:** Так, вони успадковують значення від батька. Але старі reset-стилі таргетили тільки `*`. Сучасний патерн - `*, *::before, *::after { box-sizing: border-box; }`, щоб явно охопити псевдоелементи. **Q:** Як у бібліотеці компонентів обробляти конфлікти `box-sizing` з користувацьким CSS? **A:** Стандартний підхід - задокументувати що бібліотека очікує `border-box` і попросити підключити universal reset. Для повністю ізольованих компонентів Shadow DOM не дає зовнішнім стилям впливати на внутрішні. Обидва підходи використовуються в реальних бібліотеках. ## Приклади ### content-box проти border-box поруч ```html <!DOCTYPE html> <html> <style> .content-box { box-sizing: content-box; width: 200px; padding: 20px; border: 5px solid navy; background: lightblue; margin-bottom: 12px; } .border-box { box-sizing: border-box; width: 200px; padding: 20px; border: 5px solid darkred; background: lightcoral; } </style> <div class="content-box">Реальна ширина: 250px (вміст 200 + padding 40 + border 10)</div> <div class="border-box">Реальна ширина: 200px (padding і border поміщаються всередині)</div> </html> ``` Синій блок займає 250px попри `width: 200px`. Червоний - рівно 200px. Відкрий DevTools, наведи на обидва елементи і подивись на box model у панелі справа. ### Картка як React-компонент Поширений патерн у бібліотеках компонентів. Без `border-box` додавання padding змушує картку виходити за межі контейнера і зміщувати інші елементи. ```jsx function RepoCard({ name, stars }) { return ( <div style={{ boxSizing: 'border-box', /* 300px залишається 300px навіть з padding */ width: '300px', padding: '16px', border: '1px solid #ddd', borderRadius: '6px' }}> <h3>{name}</h3> <span>⭐ {stars}</span> </div> ); } // Картка завжди займає рівно 300px, без overflow у батьківському контейнері ``` Зміна padding при hover не зміщує лейаут. Я бачив як це спричиняло помітні стрибки в продакшені, коли хтось випадково видалив глобальний reset і всі картки на сторінці одразу розширились на 32px.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.