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


274

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

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

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

Ответы:


398

Самый простой - поместить 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; }

17
Это работает, но теперь я вдвойне запутался: есть ли объяснение этому или это просто так?
DavidR

8
Да, есть объяснение, но я с тех пор забыл его :( Просто так оно и есть. overflow:hidden
Вынуждает

5
Я думаю, что объяснение overflow: hiddenздесь: ссылка . И спасибо большое, это сработало для меня
Викас Арора

6
@DavidR Самое простое объяснение состоит в том, что html / css - устаревшая, плохо продуманная и плохо реализованная технология. На самом деле, эти рассуждения объясняют множество нюансов html / css, с которыми вы, несомненно, сталкивались с тех пор, как сделали этот пост.
Небольшое

1
Имейте в виду, что это overflow: hiddenбудет просто скрывать любую часть элемента, которая вытекает из родительского контейнера. Для меня это привело к тому, что некоторые фрагменты текста стали нечитаемыми.
Top Cat

160

причина

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

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

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

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

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

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

Это также указано в 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 Поплавки , корни 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
Таким образом, всплывающие окна не распознаются их родительскими контейнерами, следовательно, высота падает, но распознаются их братьями и сестрами, следовательно, clearfix?
символическая ссылка

@symlink Да, родительские контейнеры не растут, чтобы охватить плавающие объекты, если они не являются корнями BFC. Братья и сестры, которые не являются корнями BFC, напрямую не зависят от блоков (но их линейные блоки). Однако клиренс перемещает их ниже любого предыдущего поплавка.
Ориол

«Братья и сестры, которые не являются корнями BFC, не подвержены непосредственному воздействию блоков (но их линейные блоки)». - Можете ли вы уточнить это, пожалуйста? Вы имеете в виду, что в этом jsFiddle: jsfiddle.net/aggL3Lk7/2 плавающее встроенное изображение не влияет на промежуток (следовательно, граница промежутка перекрывает его), но изображение влияет на текст (который представляет собой строковое поле), как показано из-за того, что текст не перекрывает изображение?
символическая ссылка

1
@symlink Да, именно так. Хорошо, в вашей скрипке граница принадлежит родителю, но в основном это будет то же самое для братьев и сестер: jsfiddle.net/aggL3Lk7/3
Oriol

1
Я согласен. Это должен быть принятый ответ. Мне интересно, что W3 называет способ, которым мы вынуждены кодировать, "взломать". Кто-то плохо облажался.
DR01D



11

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

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


3
Какое это имеет отношение к плавающему элементу, правильно растягивающему высоту родительского элемента?
Незначительно

11

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

display: inline-block;

вместо того

float: left;

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


11

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

.parent {display: flow-root;} 

Нет больше исправлений.

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


Работает и в Safari 11
pendingfox

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 сгибаться и применять выравнивание контента вправо или влево, и ваша проблема решена.

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