Плавающие элементы внутри div плавают за пределами div. Почему?

Скажем, у вас есть div, дайте ему определенное width и поместите в него элементы, в моем случае img и еще div.

Идея состоит в том, что содержимое контейнера div заставит контейнер div растянуться и станет фоном для содержимого. Но когда я это сделаю, содержащий div сжимается, чтобы вместить неплавающие объекты, а плавающие объекты будут либо полностью выдвинуты, либо наполовину выдвинуты, наполовину внутри и не будут иметь никакого отношения к размеру большого div.

Почему это? Есть ли что-то, что мне не хватает, и как я могу заставить плавающие элементы растягивать height содержащего div?


person DavidR    schedule 14.01.2010    source источник


Ответы (11)


Самый простой - поместить overflow:hidden в родительский div и не указывать высоту:

#parent { overflow: hidden }

Другой способ - также разместить родительский div:

#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; }
person Doug Neiner    schedule 14.01.2010
comment
Это работает, но теперь я вдвойне запутался: есть ли этому объяснение или просто так? - person DavidR; 14.01.2010
comment
Да, есть объяснение, но с тех пор я его забыл :( Просто так. overflow:hidden заставляет браузер как можно лучше содержать дочерние элементы родительского элемента. Вот почему он это исправляет. - person Doug Neiner; 14.01.2010
comment
Я думаю, что объяснение для overflow: hidden находится здесь: ссылка. И большое спасибо, это сработало для меня - person Vikas Arora; 27.02.2014
comment
@DavidR Самое простое объяснение состоит в том, что html / css - устаревшая, плохо продуманная и плохо реализованная технология. Фактически, это рассуждение фактически объясняет множество причуд html / css, с которыми вы, несомненно, столкнулись с тех пор, как сделали этот пост. - person Slight; 23.04.2015
comment
Этот ответ ничего не предлагает с точки зрения объяснения, что составляет 90% вопроса. - person Michael Benjamin; 25.09.2015
comment
Имейте в виду, что overflow: hidden просто скроет любую часть элемента, выходящую из родительского контейнера. Для меня это привело к тому, что некоторые фрагменты текста стали нечитаемыми. - person Top Cat; 23.02.2018
comment
overflow: hidden и auto оба работали для меня, но здесь разница между этими двумя. w3schools.com/cssref/pr_pos_overflow.asp скрыт - переполнение обрезается, а остальное содержимое будет невидимым. auto - если переполнение обрезается, следует добавить полосу прокрутки, чтобы увидеть остальную часть содержимого. - person Alexander; 30.05.2018
comment
Ссылка @ VikasArora не работает, но я думаю, что это еще одна ссылка на ту же статью: Магия« переполнения: скрыто » - person ChrisW; 16.05.2019
comment
Спасибо! Это помогло. - person WISERDIVISOR; 10.06.2021

Причина

Проблема в том, что плавающие элементы вне потока:

Элемент называется вне потока, если он плавающий, абсолютно позиционированный или является корневым элементом.

Следовательно, они не влияют на окружающие элементы, как элемент в потоке.

Это объясняется в 9.5 Floats:

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

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

html {
  width: 550px;
  border: 1px solid;
}
body {
  font-family: sans-serif;
  color: rgba(0,0,0,.15);
}
body:after {
  content: '';
  display: block;
  clear: both;
}
div {
  position: relative;
}
div:after {
  font-size: 200%;
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  text-align: center;
}
.block-sibling {
  border: 3px solid green;
}
.block-sibling:after {
  content: 'Block sibling';
  color: green;
}
.float {
  float: left;
  border: 3px solid red;
  height: 90px;
  width: 150px;
  z-index: 1;
}
.float:after {
  content: 'Float';
  color: red;
}
<div class="float"></div>
<div class="block-sibling">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor.
</div>

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

Учитываются только дочерние элементы в нормальном потоке (т. Е. Плавающие блоки и блоки с абсолютным позиционированием игнорируются […])

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

html {
  width: 550px;
  border: 1px solid;
}
body {
  font-family: sans-serif;
  color: rgba(0,0,0,.15);
}
body:after {
  content: '';
  display: block;
  clear: both;
}
div {
  position: relative;
}
div:after {
  font-size: 200%;
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  text-align: center;
}
.block-parent {
  border: 3px solid blue;
}
.block-parent:after {
  content: 'Block parent';
  color: blue;
}
.float {
  float: left;
  border: 3px solid red;
  height: 130px;
  width: 150px;
}
.float:after {
  content: 'Float';
  color: red;
}
<div class="block-parent">
  <div class="float"></div>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit.
</div>

Хакерское решение: оформление

Способ решения проблемы - принудительное размещение какого-либо элемента в потоке под всеми поплавками. Затем высота родительского элемента будет расти, чтобы обернуть этот элемент (и, следовательно, поплавки).

Этого можно добиться с помощью свойства clear:

Это свойство указывает, какие стороны блока (ов) элемента могут не быть смежными с более ранним плавающим блоком.

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

html {
  width: 550px;
  border: 1px solid;
}
body {
  font-family: sans-serif;
  color: rgba(0,0,0,.15);
}
body:after {
  content: '';
  display: block;
  clear: both;
}
div {
  position: relative;
}
div:after {
  font-size: 200%;
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  text-align: center;
}
.block-parent {
  border: 3px solid blue;
}
.block-parent:after {
  content: 'Block parent';
  color: blue;
}
.float {
  float: left;
  border: 3px solid red;
  height: 84px;
  width: 150px;
}
.float:after {
  content: 'Float';
  color: red;
}
.clear {
  clear: both;
  text-align: center;
  height: 37px;
  border: 3px dashed pink;
}
.clear:after {
  position: static;
  content: 'Block sibling with clearance';
  color: pink;
}
<div class="block-parent">
  <div class="float"></div>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra.
  <div class="clear"></div>
</div>

Таким образом, решение заключается в добавлении пустого элемента с clear: both в качестве последнего родственника поплавков.

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

Однако это не семантическое. Так что лучше сгенерируйте псевдоэлемент в конце родительского элемента:

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

Есть несколько вариантов этого подхода, например использование устаревшего синтаксиса с одним двоеточием :after для поддержки старых браузеров или использование других уровня блоков отображается как display: table.

Решение: корни BFC

Существует исключение из проблемного поведения, определенного в начале: если элемент блока устанавливает контекст форматирования блока (является корнем BFC), тогда он также будет переносить свое плавающее содержимое.

Согласно 10.6.7 «Авто» высоты для корней контекста форматирования блока,

Если у элемента есть плавающие потомки, нижний край поля которых находится ниже нижнего края содержимого элемента, высота увеличивается, чтобы включить эти края.

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

html {
  width: 550px;
  border: 1px solid;
}
body {
  font-family: sans-serif;
  color: rgba(0,0,0,.15);
}
body:after {
  content: '';
  display: block;
  clear: both;
}
div {
  position: relative;
}
div:after {
  font-size: 200%;
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  text-align: center;
}
.block-parent {
  border: 3px solid blue;
}
.block-parent.bfc-root:after {
  content: 'BFC parent';
  color: blue;
}
.float {
  float: left;
  border: 3px solid red;
  height: 127px;
  width: 150px;
}
.float:after {
  content: 'Float';
  color: red;
}
.bfc-root {
  overflow: hidden;
}
<div class="block-parent bfc-root">
  <div class="float"></div>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit.
</div>

Кроме того, как объяснялось в 9.5 Floats, корни BFC также полезны по следующим причинам:

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

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

html {
  width: 550px;
  border: 1px solid;
}
body {
  font-family: sans-serif;
  color: rgba(0,0,0,.15);
}
body:after {
  content: '';
  display: block;
  clear: both;
}
div {
  position: relative;
}
div:after {
  font-size: 200%;
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  text-align: center;
}
.block-sibling {
  border: 3px solid green;
}
.block-sibling.bfc-root:after {
  content: 'BFC sibling';
  color: green;
}
.float {
  float: left;
  border: 3px solid red;
  height: 90px;
  width: 150px;
  z-index: 1;
}
.float:after {
  content: 'Float';
  color: red;
}
.bfc-root {
  overflow: hidden;
}
<div class="float"></div>
<div class="block-sibling bfc-root">
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur.
</div>

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

  • Блокируйте блоки с 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.

Display L3 решает следующие проблемы:

Созданы файлы flow и flow-root внутренние типы отображения для лучшего отображения макета потока. display types и создать явный переключатель для превращения элемента в корень BFC. (Это должно устранить необходимость в таких хаках, как ::after { clear: both; } и overflow: hidden […])

К сожалению, поддержки браузеров пока нет. В конце концов, мы сможем использовать

.bfc-root {
  display: flow-root;
}
person Oriol    schedule 30.08.2015
comment
Таким образом, плавающие боксы не распознаются их родительскими контейнерами, что приводит к уменьшению высоты, но распознаются их братьями и сестрами, отсюда и clearfix? - person symlink; 21.02.2016
comment
@symlink Да, родительские контейнеры не растут, чтобы содержать поплавки, если они не являются корнями BFC. На братьев и сестер, которые не являются корнями BFC, блоки не влияют напрямую (но на их строчные блоки). Однако зазор перемещает их ниже любого предыдущего поплавка. - person Oriol; 21.02.2016
comment
На братьев и сестер, которые не являются корнями BFC, блоки не влияют напрямую (но на их строчные блоки). - Не могли бы вы прояснить это? Вы имеете в виду, что в этом jsFiddle: jsfiddle.net/aggL3Lk7/2 плавающее встроенное изображение не влияет на диапазон (следовательно, граница диапазона перекрывает его), но изображение влияет на текст (который является строковым блоком), как показывает тот факт, что текст не перекрывает изображение? - person symlink; 21.02.2016
comment
@symlink Да, именно так. Что ж, в вашей скрипке граница принадлежит родителю, но для братьев и сестер она будет в основном такой же: jsfiddle.net / aggL3Lk7 / 3 - person Oriol; 21.02.2016
comment
Я согласен. Это должен быть принятый ответ. Мне интересно, что W3 вызывает то, как нас заставляют кодировать взлом. Кто-то плохо облажался. - person DR01D; 31.01.2017

Поместите плавающий div(s) в div и в CSS укажите overflow:hidden;, и он будет работать нормально.

person Nad    schedule 14.07.2011
comment
Я пробовал это, но это не решило проблему: stackoverflow.com/questions/25329349/ - person SearchForKnowledge; 15.08.2014

Рекомендация W3Schools:

поместите overflow: auto на родительский элемент, и он будет «окрашивать» весь фон, включая поля элементов. Также плавающие элементы останутся внутри границы.

http://www.w3schools.com/css/tryit.asp?filename=trycss_layout_clearfix

person mggluscevic    schedule 05.03.2016

Вот более современный подход:

.parent {display: flow-root;} 

Больше никаких исправлений.

p.s. Использование переполнения: скрыто; скрывает тень коробки так ...

person pendingfox    schedule 01.12.2017
comment
Также работает в Safari 11 - person pendingfox; 23.12.2017

В некоторых случаях, например, когда (если) вы просто используете float, чтобы элементы располагались в одной «строке», вы можете использовать

display: inline-block;

вместо

float: left;

В противном случае использование элемента clear в конце будет работать, даже если это может идти вразрез с необходимостью элемента для выполнения того, что должно быть работой CSS.

person LSerni    schedule 26.09.2015

Ничего не пропало. Float был разработан для случая, когда вы хотите, чтобы изображение (например) располагалось рядом с несколькими абзацами текста, чтобы текст обтекал изображение. Этого бы не произошло, если бы текст «растягивал» контейнер. Ваш первый абзац заканчивался, а затем следующий абзац начинался под изображением (возможно, на несколько сотен пикселей ниже).

И поэтому вы получаете такой результат.

person Lucas Wilson-Richter    schedule 14.01.2010
comment
Как это имеет какое-либо отношение к плавающему элементу, правильно растягивающему высоту родительского элемента? - person Slight; 23.04.2015

Спасибо, 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>
person Flyout91    schedule 23.11.2016

Как говорит Лукас, вы описываете предполагаемое поведение свойства float. Многих смущает то, что float был выведен далеко за рамки его первоначального предполагаемого использования, чтобы восполнить недостатки в модели макета CSS.

Взгляните на Floatutorial, если вы хотите лучше понять, как работает это свойство. .

person Sam Murray-Sutton    schedule 14.01.2010

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

<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>

person Vijay Tiwari    schedule 04.04.2020

Другие решения здесь не работали для меня - мои элементы продолжали отключаться. Но если кто-то еще приходит сюда с помощью начальной загрузки, мне удалось явно установить поля оси X промежуточной строки div на ноль, а также установить justify-content-between:

<div class='container p-2'>
  <div class='row mx-0 justify-content-between'>
    <div class='float-left'></div>
    <div class='float-right'></div>
  </div>
</div>
person byron broughten    schedule 11.03.2021