Властивість CSS overflow
CSS overflow визначає, що відбувається з контентом, який не вміщується в контейнер: він може вийти за межі, обрізатися або стати прокручуваним.
Теорія
Коротко
- Уявіть акваріум:
visibleдає воді розтекатися,hiddenгерметично запечатує,scrollдодає постійні трубки,autoдодає їх тільки коли вода переповнюється. - Головна різниця між
autoіscroll:autoпоказує скролбар тільки коли контент виходить за межі;scrollзавжди його рендерить. overflow: hiddenстворює Block Formatting Context (BFC), який автоматично огортає флоатовані елементи.- Правило вибору:
hiddenдля чіткого обрізання UI (картки, аватари),autoдля динамічного контенту як чати або сайдбари.
Швидкий приклад
/* Обрізає дочірній контент до форми картки */
.card {
overflow: hidden;
border-radius: 12px;
width: 300px;
height: 200px;
}
/* Скролбар з'являється тільки коли повідомлення переповнюють контейнер */
.chat {
overflow-y: auto;
max-height: 400px; /* Без цього контейнер просто росте нескінченно */
}Перше правило обрізає все що виходить за межі картки. Друге фіксує висоту списку повідомлень і додає вертикальний скролбар тільки за потреби.
Значення
| Значення | Поведінка |
|---|---|
visible | За замовчуванням. Контент рендериться за межами блоку. |
hidden | Обрізає контент. Без скролбара. JS scrollTop працює. |
scroll | Скролбар завжди видимий, навіть на короткому контенті. |
auto | Скролбар з'являється тільки при переповненні. |
clip | Як hidden, але JS scrollTop не має ефекту. |
Ключова різниця
auto і scroll обидва роблять контент прокручуваним, але scroll завжди рендерить доріжку скролбара незалежно від розміру контенту. На деяких платформах це резервує місце і зміщує layout. auto - безпечніший варіант для більшості ситуацій. scroll має сенс коли потрібно щоб скролбар завжди був присутній візуально, наприклад у горизонтальній навігації де ви хочете показати що контент продовжується за межами екрана.
overflow-x та overflow-y
Осі можна контролювати незалежно:
/* Горизонтальний скрол, вертикальне переповнення приховане */
.tag-list {
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
-webkit-overflow-scrolling: touch; /* Нативне відчуття на iOS */
}Цей патерн зустрічається в списках тегів, горизонтальних каруселях і Bootstrap-компоненті .table-responsive.
Коли застосовувати
- Картка з довгим текстом:
overflow: hidden(чисте обрізання) - Чат, сайдбар, тіло модального вікна:
overflow-y: autoзmax-height - Горизонтальна навігація або таблиця даних:
overflow-x: autoдля мобільних - Елемент
bodyпри відкритті модалки:overflow: hiddenблокує фоновий скрол - Картка з округленими кутами або аватар:
overflow: hiddenобрізає зображення до форми контейнера
overflow: hidden та BFC
Встановлення overflow в hidden, auto або scroll створює Block Formatting Context (контекст форматування блоку). Практичний результат: контейнер огортає флоатовані дочірні елементи замість того щоб зколапсуватися до нульової висоти. Це був стандартний спосіб очистки флоатів до появи display: flow-root. У старих кодових базах такий підхід зустрічається досі.
.container {
overflow: hidden; /* BFC: огортає флоатовані елементи, без колапсу висоти */
}Типові помилки
Забути висоту при overflow: auto.
/* Неправильно: контейнер росте нескінченно, скрол не спрацьовує */
.list { overflow-y: auto; }
/* Правильно */
.list { overflow-y: auto; height: 300px; }Без обмеження висоти контейнер просто розтягується. Нема чого переповнювати.
Вважати що overflow: hidden обрізає обидві осі.
/* Дочірній елемент може виходити горизонтально */
.parent { overflow: hidden; }
.child { width: 500px; }
/* Вкажіть потрібну вісь явно */
.parent { overflow-x: hidden; }Використовувати overflow: scroll на мобільних. Постійно видимий скролбар може конфліктувати з нативним прокручуванням і створювати подвійні доріжки. Краще overflow: auto з -webkit-overflow-scrolling: touch.
Плутати hidden і clip. Обидва обрізають контент візуально. clip також блокує JS scrollTop. Якщо потрібно керувати позицією скролу в коді, використовуйте hidden.
Де зустрічається на практиці
- shadcn/ui Dialog:
overflow: autoна.modal-bodyдля прокручуваного контенту модалки - TailwindCSS: клас
overflow-hiddenна картках в шаблонах Next.js - Bootstrap:
.table-responsiveвикористовуєoverflow-x: autoдля широких таблиць на мобільних - VS Code: панелі сайдбара комбінують
overflow: hiddenз ресайз-хендлерами
Питання на співбесіді
Q: Яка різниця між overflow: hidden і overflow: clip?
A: Обидва обрізають контент візуально. clip додатково блокує всі scroll-події, зокрема JS scrollTop. hidden дозволяє програмне прокручування. Якщо потрібно змінювати позицію скролу в коді, використовуйте hidden.
Q: Як overflow взаємодіє з flexbox?
A: Встановлення overflow на flex-контейнері тільки обрізає або прокручує вміст. На вирівнювання flex-елементів воно не впливає. Щоб окремий flex-елемент прокручувався, ставте overflow на нього, не на контейнер.
Q: Чому overflow-x: auto не показує скролбар коли контент влазить?
A: Браузери приховують доріжку скролбара поки контент не переповниться. Це і є суть auto. Якщо потрібна постійна доріжка, використовуйте scroll.
Q: Як overflow: hidden на body блокує фоновий скрол при модалці і що ламається в iOS Safari?
A: Він обрізає прокручуваний вміст body, тому користувач не може скролити за модалкою. iOS Safari може обійти це через momentum scroll. Фікс: body { overflow: hidden; position: fixed; width: 100%; }. Майте на увазі, що це скидає scrollY до 0, тому позицію потрібно зберегти і відновити вручну.
Приклади
Обрізання зображення до форми картки
<style>
.card {
width: 250px;
height: 180px;
overflow: hidden;
border-radius: 12px;
}
.card img {
width: 100%;
height: 100%;
object-fit: cover;
}
</style>
<div class="card">
<img src="photo.jpg" alt="Фото профілю" />
</div>Без overflow: hidden кути зображення виходять за межі округленого бордера. З ним зображення обрізається по формі картки. Саме такий патерн TailwindCSS використовує на картках у своїх шаблонах.
Прокручуваний контейнер чату
function ChatMessages({ messages }) {
return (
<div style={{
height: '400px',
overflowY: 'auto', /* Скрол тільки за потреби */
border: '1px solid #ccc',
padding: '8px'
}}>
{messages.map(msg => (
<div key={msg.id}>{msg.text}</div>
))}
</div>
);
}Контейнер залишається фіксованим на 400px. Як тільки повідомлення перевищують цю висоту, з'являється скролбар. Приберіть height: 400px і скролбар не з'явиться ніколи, скільки б повідомлень не завантажилося. Це найпоширеніша помилка яку зустрічаю на код-рев'ю.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.