Skip to main content

Методи очищення CSS

Методи очищення CSS - прийоми, які змушують батьківський контейнер охоплювати дочірні плаваючі елементи (float) після того, як ті вийшли з нормального потоку документа.

Теорія

TL;DR

  • Float виводить елементи з нормального потоку, тому батько не враховує їх висоту і колапсує до 0
  • Clearfix через ::after - стандартне рішення для float-макетів
  • overflow: hidden створює BFC, але обрізає дочірні елементи з position: absolute
  • display: flow-root - чистий варіант без побічних ефектів
  • Flexbox і Grid цієї проблеми не мають взагалі

Чому батько колапсує

Коли застосовуєш float: left або float: right до дочірнього елемента, браузер виводить його з нормального потоку. Батько рахує висоту тільки по блокових елементах, що залишились у потоці. Float-елементи в цей розрахунок не потрапляють. Тому контейнер, де є тільки плаваючі діти, отримує height: 0.

Нижче червона рамка рендериться як пряма лінія:

css
.container { border: 2px solid red; } .box { float: left; width: 100px; height: 100px; }
html
<div class="container"> <div class="box"></div> <div class="box"></div> </div> <!-- Рамка - пряма лінія. Блоки виходять за межі. -->

Метод clearfix

Найпоширеніший спосіб. Додаємо ::after псевдоелемент до батька:

css
.clearfix::after { content: ""; display: table; clear: both; }

Клас ставиться на батька, не на плаваючі дочірні елементи:

html
<div class="container clearfix"> <div class="box" style="float: left;"></div> <div class="box" style="float: left;"></div> </div>

clear: both позиціонує псевдоелемент нижче за всі попередні float-елементи. Батько змушений включити його у висоту. Жодного зайвого HTML. Bootstrap 3 і 4 використовували саме такий підхід у навбарах і медіа-компонентах.

Важливо не плутати: clear - це CSS-властивість, clearfix - назва техніки, яка використовує clear всередині псевдоелемента. Це різні речі.

Метод overflow

css
.container { overflow: hidden; }

Будь-яке значення overflow, крім visible, створює новий контекст форматування блоку (block formatting context, BFC). BFC зобов'язаний містити свої float-нащадки, тому висота більше не колапсує. Зручно, але є ризик: overflow: hidden обрізає дочірні елементи з position: absolute, якщо ті виходять за межі контейнера. Баг з обрізаним тултіпом через це - класика старих кодових баз. Використовуй тільки коли точно знаєш, що нічого не має виходити за межі.

display: flow-root

css
.container { display: flow-root; }

Створює BFC без побічних ефектів. Без обрізання, без скролбарів, без псевдоелементів. Підтримується всіма сучасними браузерами з 2018 року. Якщо пишеш новий код з float (HTML-листи для розсилок, наприклад), це правильний вибір.

Коли що використовувати

  • Підтримка Bootstrap 3/4 або старих WordPress-тем: clearfix вже є в проекті, залишай його
  • Швидке виправлення і немає абсолютно позиціонованих дітей: overflow: hidden
  • Новий код з float (email-розсилки): display: flow-root
  • Нові макети: відмовся від float і використовуй Flexbox або Grid

Типові помилки

clear: both на самому плаваючому елементі:

css
.box { float: left; clear: both; } /* Батько все одно колапсує */

clear каже елементу, де стати відносно попередніх float-елементів. Але плаваючий елемент вже виведений з потоку, і клірингування себе самого на висоту батька не впливає. Виправлення треба ставити на псевдоелемент батька або на сусідній елемент після плаваючих.

overflow: hidden коли є абсолютно позиціоновані діти:

css
.container { overflow: hidden; position: relative; } /* Дропдаун або тултіп з position: absolute буде обрізаний */

Класичний баг у старих проектах. Clearfix або flow-root вирішують це без обрізання.

Clearfix на inline-елементі:

display: table всередині ::after вимагає блокового контексту батька. Якщо батько має display: inline, псевдоелемент поводитиметься неправильно і макет ламається без жодних помилок у консолі. Clearfix ставиться тільки на блокові елементи.

Follow-up питання

Q: Що таке block formatting context (BFC) і як clearing пов'язаний з ним?
A: BFC - ізольована область розмітки, де float-елементи містяться всередині, а відступи не виходять назовні. overflow: hidden і display: flow-root створюють BFC, змушуючи контейнер враховувати висоту float-дітей. Clearfix діє інакше: вставляє блок після float-елементів, що опускає нижній край батька.

Q: Чому display: table використовується в clearfix ::after?
A: display: table генерує блоковий бокс, на який діє clear: both. Цей бокс позиціонується нижче за всі попередні float-елементи. Бонус - він також запобігає злиттю відступів (margin collapse) між псевдоелементом і дочірніми елементами.

Q: clearfix чи display: flow-root - що обирати?
A: flow-root чистіший і не має побічних ефектів. Clearfix потрібен тільки при підтримці старого коду, де він вже використовується, або для браузерів до 2018 року.

Q: Чи працює clearfix всередині flex-контейнера?
A: Ні. Всередині Flexbox float-елементи ігноруються, тому clearfix немає що очищати. Проблеми з колапсом висоти через float там просто не виникає.

Приклади

Базовий: колапс батька і виправлення

html
<!DOCTYPE html> <html> <head> <style> .container { border: 2px solid red; margin-bottom: 20px; } .box { float: left; width: 80px; height: 80px; background: steelblue; margin: 8px; } .clearfix::after { content: ""; display: table; clear: both; } </style> </head> <body> <!-- Зламано: рамка колапсує в лінію --> <div class="container"> <div class="box"></div> <div class="box"></div> </div> <!-- Виправлено: рамка охоплює обидва блоки --> <div class="container clearfix"> <div class="box"></div> <div class="box"></div> </div> </body> </html>

Перший контейнер - плоска червона лінія. Другий охоплює блоки повністю. Різниця тільки в класі clearfix на батьку.

Реальний кейс: медіа-об'єкт (патерн Bootstrap 3)

html
<article class="media clearfix"> <img src="avatar.jpg" style="float: left; width: 64px; margin-right: 12px;"> <div class="media-body"> <h4>Заголовок поста</h4> <p>Текст розташовується поряд з картинкою. Висота батька підлаштовується автоматично.</p> </div> </article>
css
.media::after { content: ""; display: table; clear: both; }

Саме такий патерн використовував Bootstrap 3 у компоненті .media. Без clearfix тег <article> колапсує до висоти тексту і картинка виходить за межі картки.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?