Плаваючі елементи всередині 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.