Плаваючі елементи всередині div, плавають поза div. Чому?


274

Скажіть, у вас є div, дайте йому певне значення widthі вкладіть у нього елементи, в моєму випадку imgі інше div.

Ідея полягає в тому, що вміст контейнера divзмусить контейнер divрозтягуватися і буде фоном для вмісту. Але коли я це роблю, що містять divусадку, щоб вмістити об'єкти, що не плавають, і плаваючі предмети будуть або на всьому шляху, або навпіл, навпіл, і не матимуть жодного відношення до великого великого div.

Чому це? Чи щось мені не вистачає, і як я можу змусити плаваючі предмети розтягувати heightвміст div?

Відповіді:


397

Найпростіше - надіти overflow:hiddenбатьківський div і не вказати висоту:

#parent { overflow: hidden }

Інший спосіб - також плавати батьківським дівом:

#parent { float: left; width: 100% }

Інший спосіб використовує чіткий елемент:

<div class="parent">
   <img class="floated_child" src="..." />
   <span class="clear"></span>
</div>

CSS

span.clear { clear: left; display: block; }

17
Це працює, але зараз я вдвічі розгублений: чи є це пояснення чи це просто так?
DavidR

8
Так, є пояснення, але я його забув :( Це як воно є. Сила overflow:hiddenбраузера якнайкраще вміщує дочірні елементи батьків. Ось чому це і виправляє.
Дуг Нейнер,

5
Думаю, пояснення overflow: hiddenтут: посилання . І велике спасибі, це спрацювало для мене
Вікас Арора,

6
@DavidR Найпростішим поясненням є те, що html / css - це датований, погано продуманий та погано реалізований фрагмент технології. Насправді, це міркування насправді пояснює багато химерностей html / css, з якими ви, без сумніву, стикалися, коли ви зробили цю публікацію.
Невеликий

1
Майте на увазі, що overflow: hiddenпросто буде прихована будь-яка частина елемента, яка витікає з батьківського контейнера. Для мене це призвело до того, що певні шматочки тексту стали нечитабельними.
Топ Кіт

160

Причина

Проблема полягає в тому, що плаваючі елементи витікають :

Елемент викликається потоком, якщо він плаває, абсолютно розташований або є кореневим елементом.

Отже, вони не впливають на навколишні елементи, як це було б вхідним елементом.

Це пояснено в 9,5 поплавків :

Оскільки поплавця немає в потоці, нерозміщені блокові коробки, створені до і після поплавкового поля, протікають вертикально, як ніби поплавця не існувало. Однак поточні та наступні поля рядків, створені поруч з поплавком, скорочуються в міру необхідності, щоб звільнити поле для поля поплавця.

введіть тут опис зображення

Це також зазначено в 10.6 Розрахунок висоти та запасів . Для "звичайних" блоків ,

Враховуються лише діти у звичайному потоці (тобто плаваючі коробки та абсолютно розташовані коробки ігноруються […])

введіть тут опис зображення

Хакі рішення: кліренс

Спосіб вирішення проблеми - примусити якийсь елемент в потоці розмістити нижче всіх плавців. Тоді зріст висоти батьків буде зростати, щоб обернути цей елемент (і, таким чином, плаває теж).

Це може бути досягнуто з використанням в clearвласності :

Це властивість вказує, які сторони вікон (ив) елемента можуть не примикати до попереднього плаваючого поля.

введіть тут опис зображення

Таким чином, рішення - це додавання порожнього елемента з clear: bothостанніми побратимами плавців

<div style="clear: both"></div>

Однак це не семантично. Тому краще генерувати псевдоелемент у кінці батьків:

.clearfix::after {
  clear: both;
  display: block;
}

Існує кілька варіантів цього підходу, наприклад, використання застарілого синтаксису одиничної кишки :afterдля підтримки старих браузерів або використання інших дисплеїв рівня блоківdisplay: table .

Рішення: коріння BFC

Існує виняток із проблемної поведінки, визначеної на початку: якщо елемент блоку встановлює контекст форматування блоків (є коренем BFC), він також загортатиме свій плаваючий вміст.

Відповідно до 10.6.7 "Авто" висоти для блокування кореневого контексту блоку ,

Якщо в елементі є плаваючі нащадки, нижній край яких знаходиться нижче нижнього краю вмісту елемента, то висота збільшується, щоб включати ці краї.

введіть тут опис зображення

Крім того, як пояснено 9.5 Floats , коріння BFC також корисні через наступне:

Поле рамки таблиці, елемент, що замінений на рівні блоку, або елемент у звичайному потоці, який встановлює новий контекст форматування блоку […], не повинен перекривати поле маржування будь-яких плавців у тому ж контексті форматування блоку, що і сам елемент .

введіть тут опис зображення

Контекст форматування блоку встановлює

  • Блокові блоки з overflowіншими, ніж visible, наприклад,hidden

    .bfc-root {
      overflow: hidden;
      /* display: block; */
    }
  • Блокуйте контейнери, які не є блоковими полями: коли displayвстановлено значення inline-block, table-cellабо table-caption.

    .bfc-root {
      display: inline-block;
    }
  • Плаваючі елементи: коли floatвстановлено значення leftабо right.

    .bfc-root {
      float: left;
    }
  • Абсолютно розміщені елементи: коли positionвстановлено значення absoluteабо fixed.

    .bfc-root {
      position: absolute;
    }

Зверніть увагу, що вони можуть мати небажані побічні ефекти, як, наприклад, відсікання переповненого вмісту, обчислення автоматичної ширини за допомогою алгоритму зменшення до розміру або виходу з потоку. Отже, проблема полягає в тому, що неможливо мати елемент рівня на потоці блоку з видимим переповненням, який встановлює BFC.

Відображення L3 вирішує ці проблеми:

Створено flowта внутрішні типи дисплея для кращого вираження типів відображення макетів потоку та створення явного перемикача для створення елемента коренем BFC . (Це повинно усунути потребу в таких хаках як і […])flow-root ::after { clear: both; }overflow: hidden

На жаль, поки немає підтримки браузера. Врешті-решт, ми можемо використовувати

.bfc-root {
  display: flow-root;
}

1
Так плаваючі ящики не розпізнаються їхніми батьківськими контейнерами, отже, висота згортається, але розпізнається їх побратимами, отже, виправлення?
symlink

@symlink Так, батьківські контейнери не переростають у закриті поплавці, якщо вони не є коренями BFC. Брати, які не мають коренів BFC, не впливають безпосередньо на блоки (але їх рядки є). Однак зазор переміщує їх нижче будь-якого попереднього поплавця.
Оріол

"Брати та сестри, які не мають коренів BFC, не впливають безпосередньо на блоки (але їх рядки є)." - Чи можете ви уточнити це, будь ласка? Ви маєте на увазі, що в цьому jsFiddle: jsfiddle.net/aggL3Lk7/2 плаваюче вбудоване зображення не впливає на проміжок (отже, облямівка діапазону перекриває його), але зображення впливає на текст (який є рядок рядка), як показано тим, що текст не перекриває зображення?
symlink

1
@symlink Так, точно. Що ж, у вашій скрипці кордон належить батьківському, але це було б в основному однаковим для братів і сестер: jsfiddle.net/aggL3Lk7/3
Oriol

1
Я погоджуюсь. Це має бути прийнятою відповіддю. Мені цікаво, що W3 називає так, як ми змушені кодувати "хак". Хтось погано викрутив.
DR01D



11

Нічого не бракує. Поплавок був розроблений для випадку, коли ви хочете, щоб зображення (наприклад) сиділо поруч з кількома абзацами тексту, тому текст обтікається навколо зображення. Це не сталося, якби текст "розтягнув" контейнер. Ваш перший абзац закінчиться, і тоді ваш наступний абзац розпочнеться під зображенням (можливо, кілька сотень пікселів нижче).

І тому ви отримуєте результат, який ви є.


3
Як це має відношення до того, що плаваючий елемент правильно розтягує висоту батьківського?
Невеликий

11

У деяких випадках, наприклад, коли (якщо) ви просто використовуєте floatдля того, щоб елементи перетікали одну й ту саму "лінію", ви можете використовувати

display: inline-block;

замість

float: left;

В іншому випадку використання clearелемента в кінці працює, навіть якщо воно може суперечити зерну, потрібен елемент, щоб виконати те, що повинно бути роботою CSS.


11

Ось більш сучасний підхід:

.parent {display: flow-root;} 

Більше не буде чітких виправлень.

ps Використання переповнення: приховано; приховує коробку-тінь так ...


Працює і в Safari 11
очікує

7

Дякую, LSerni, що ти вирішив це для мене.

Щоб досягти цього:

+-----------------------------------------+
| +-------+                     +-------+ |
| | Text1 |                     | Text1 | |
| +-------+                     +-------+ |
|+----------------------------------------+

Ви повинні зробити це:

<div style="overflow:auto">
    <div style="display:inline-block;float:left"> Text1 </div>
    <div style="display:inline-block;float:right"> Text2 </div>
</div>

4

Як каже Лукас, те, що ви описуєте, - це призначена поведінка для властивості float. Багатьох людей бентежить те, що float був висунутий далеко за межі свого початкового використання, щоб компенсувати недоліки в моделі компонування CSS.

Погляньте на Floatutorial, якщо ви хочете краще зрозуміти, як працює ця властивість.


0

Ви можете легко зробити спочатку, ви можете зробити div flex і застосувати виправдовувати вміст праворуч або ліворуч, і ваша проблема вирішена.

<div style="display: flex;padding-bottom: 8px;justify-content: flex-end;">
					<button style="font-weight: bold;outline: none;background-color: #2764ff;border-radius: 3px;margin-left: 12px;border: none;padding: 3px 6px;color: white;text-align: center;font-family: 'Open Sans', sans-serif;text-decoration: none;margin-right: 14px;">Sense</button>
				</div>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.