# Свойство "float" Свойство `float` в CSS занимает особенное место. До его появления расположить два блока один слева от другого можно было лишь при помощи таблиц. Но в его работе есть ряд особенностей. Поэтому его иногда не любят, но при их понимании `float` станет вашим верным другом и помощником. Далее мы рассмотрим, как работает `float`, разберём решения сопутствующих проблем, а также ряд полезных рецептов. [cut] ## Как работает float [#float-algorithm] Синтаксис: ```css float: left | right | none | inherit; ``` При применении этого свойства происходит следующее:
  1. Элемент позиционируется как обычно, а затем *вынимается из документа потока* и сдвигается влево (для `left`) или вправо (для `right`) до того как коснётся либо границы родителя, либо другого элемента с `float`.
  2. Если пространства по горизонтали не хватает для того, чтобы вместить элемент, то он сдвигается вниз до тех пор, пока не начнёт помещаться.
  3. Другие непозиционированные блочные элементы без `float` ведут себя так, как будто элемента с `float` нет, так как он убран из потока.
  4. Строки (inline-элементы), напротив, "знают" о `float` и обтекают элемент по сторонам.
Ещё детали:
  1. Элемент при наличии `float` получает `display:block`. То есть, указав элементу, у которого `display:inline` свойство `float: left/right`, мы автоматически сделаем его блочным. В частности, для него будут работать `width/height`. Исключением являются некоторые редкие `display` наподобие `inline-table` и `run-in` (см. [Relationships between 'display', 'position', and 'float'](http://www.w3.org/TR/CSS2/visuren.html#dis-pos-flo))
  2. Ширина `float`-блока определяется по содержимому. (["CSS 2.1, 10.3.5"](http://www.w3.org/TR/CSS2/visudet.html#float-width)).
  3. Вертикальные отступы `margin` элементов с `float` не сливаются с отступами соседей, в отличие от обычных блочных элементов.
Это пока только теория. Далее мы рассмотрим происходящее на примере. ### Текст с картинками Одно из первых применений `float`, для которого это свойство когда-то было придумано -- это вёрстка текста с картинками, отжатыми влево или вправо. Например, вот страница о Винни-Пухе с картинками, которым поставлено свойство `float`: Её HTML-код ([edit src="winnie"]открыть[/edit]) выглядит примерно так: ```html

Текст...

Текст...

Текст...

Текст...

``` Каждая картинка, у которой есть `float`, обрабатывается в точности [по алгоритму](#float-algorithm), указанному выше. Посмотрим, например, как выглядело бы начало текста без float: [iframe src="winnie-nofloat" height=300 border=1 link edit]
  1. Элемент `IMG` вынимается из документа потока. Иначе говоря, последующие блоки начинают вести себя так, как будто его нет, и заполняют освободившееся место (изображение для наглядности полупрозрачно): [iframe src="winnie-nofloat-1" height=250 border=1 link edit]
  2. Элемент `IMG` сдвигается максимально вправо(при `float:right`): [iframe src="winnie-nofloat-2" height=250 border=1 link edit]
  3. Строки, в отличие от блочных элементов, "чувствуют" `float` и уступают ему место, обтекая картинку слева: [iframe src="winnie-nofloat-3" height=250 border=1 link edit]
При `float:left` -- всё то же самое, только `IMG` смещается влево (или не смещается, если он и так у левого края), а строки -- обтекают справа **Строки и инлайн-элементы смещаются, чтобы уступить место `float`. Обычные блоки -- ведут себя так, как будто элемента нет.** Чтобы это увидеть, добавим параграфам фон и рамку, а также сделаем изображение немного прозрачным: [iframe src="winnie-block-bg" height=300 border=1 link edit] Как видно из рисунка, параграфы проходят "за" `float`. При этом строки в них о `float'ах` знают и обтекают их, поэтому соответствующая часть параграфа пуста. ### Блок с float Свойство `float` можно поставить любому элементу, не обязательно картинке. При этом элемент станет блочным. Посмотрим, как это работает, на конкретной задаче -- сделать рамку с названием вокруг картинки с Винни. HTML будет такой: ```html

Винни-Пух

*!*
Кадр из советского мультфильма
*/!*

Текст...

``` ..То есть, `div.left-picture` включает в себя картинку и заголовок к ней. Добавим стиль с `float`: ```css .left-picture { *!* float: left; */!* /* рамочка и отступ для красоты (не обязательно) */ margin: 0 10px 5px 0; text-align: center; border: 1px solid black; } ``` Результат: [iframe src="winnie-block" height=300 border=1 link edit] Заметим, что блок `div.left-picture` "обернул" картинку и текст под ней, а не растянулся на всю ширину. Это следствие того, что ширина блока с `float` определяется по содержимому. ## Очистка под float Разберём еще одну особенность использования свойства `float`. Для этого выведем персонажей из мультфильма "Винни-Пух". Цель: [iframe src="winnie-clear-3" height=600 border=1 link edit] Реализуем её, шаг за шагом. ### Шаг 1. Добавляем информацию Попробуем просто добавить Сову после Винни-Пуха: ```html

Винни-Пух

Картинка

..Текст о Винни..

Сова

Картинка

..Текст о Сове..

``` Результат [edit src="winnie-clear-1"]такого кода[/edit] будет странным, но предсказуемым: [iframe src="winnie-clear-1" border="1" height=500 link edit] Произошло следующее: ### Шаг 2. Свойство clear Мы, конечно же, хотели бы расположить заголовок "Сова" и остальную информацию ниже Винни-Пуха. Для решения возникшей проблемы придумано свойство `clear`. Синтаксис: ```css clear: left | right | both; ``` Применение этого свойства сдвигает элемент вниз до тех пор, пока не закончатся `float'ы` слева/справа/с обеих сторон. Применим его к заголовку `H2`: ```css h2 { clear: left; } ``` Результат [edit src="winnie-clear-2"]получившегося кода[/edit] будет ближе к цели, но всё еще не идеален: Элементы теперь в нужном порядке. Но куда пропал отступ `margin-top` у заголовка "Сова"? Теперь заголовок "Сова" прилегает снизу почти вплотную к картинке, с учётом её `margin-bottom`, но без своего большого отступа `margin-top`. Таково поведение свойства `clear`. Оно сдвинуло элемент `h2` вниз ровно настолько, чтобы элементов `float` не было *сбоку от его верхней границы*. Если посмотреть на элемент заголовка внимательно в инструментах разработчика, то можно заметить отступ `margin-top` у заголовка по-прежнему есть, но он располагается "за" элементом `float` и не учитывается при работе в `clear`. Чтобы исправить ситуацию, можно добавить перед заголовком пустой промежуточный элемент без отступов, с единственным свойством `clear:both`. Тогда уже под ним отступ заголовка будет работать нормально: ```html

Винни-Пух

Картинка

Текст

*!*
*/!*

Сова

Картинка

Текст

``` Результат [edit src="winnie-clear-3"]получившегося кода[/edit]: [iframe src="winnie-clear-3" border="1" height=600 link edit] ## Заполнение блока-родителя Итак, мы научились располагать другие элементы *под* `float`. Теперь рассмотрим следующую особенность. **Из-за того, что блок с `float` удалён из потока, родитель не выделяет под него места.** Например, выделим для информации о Винни-Пухе красивый элемент-контейнер `
`: ```html

Винни-Пух

Картинка

Текст.

``` Стиль контейнера: ```css .hero { background: #D2B48C; border: 1px solid red; } ``` Результат [edit src="winnie-clear-4"]получившегося кода[/edit]: [iframe src="winnie-clear-4" border="1" height=300 link edit] Элемент с `float` оказался выпавшим за границу родителя `.hero`. Чтобы этого не происходило, используют одну из следующих техник. ### Поставить родителю float Элемент с `float` обязан расшириться, чтобы вместить вложенные `float`. Поэтому, если это допустимо, то установка `float` контейнеру всё исправит: ```css .hero { background: #D2B48C; border: 1px solid red; *!* float: left; */!* } ``` [iframe src="winnie-clearfill-float" border="1" height=300 link edit] Разумеется, не всегда можно поставить родителю `float`, так что смотрим дальше. ### Добавить в родителя элемент с clear Добавим элемент `div style="clear:both"` в самый конец контейнера `.hero`. Он с одной стороны будет "нормальным" элементом, в потоке, и контейнер будет обязан выделить под него пространство, с другой -- он знает о `float` и сместится вниз. Соответственно, и контейнер вырастет в размере: ```html

Винни-Пух

Картинка

Текст.

*!*
*/!*
``` Результат -- правильное отображение, как и в примере выше. [edit src="winnie-clearfill-div"]Открыть код[/edit]. Единственный недостаток этого метода -- лишний HTML-элемент в разметке. ### Универсальный класс clearfix Чтобы не добавлять в HTML-код лишний элемент, можно задать его через `:after`. ```css .clearfix:after { content: "."; /* добавить содержимое: "." */ display: block; /* сделать блоком, т.к. inline не может иметь clear */ clear: both; /* с обеих сторон clear */ visibility: hidden; /* сделать невидимым, зачем нам точка внизу? */ height: 0; /* сделать высоту 0, чтобы не занимал место */ } ``` Добавив этот класс к родителю, получим тот же результат, что и выше. [edit src="winnie-clearfill-clearfix"]Открыть код[/edit]. ### overflow:auto/hidden Если добавить родителю `overflow: hidden` или `overflow: auto`, то всё станет хорошо. ```css .hero { *!* overflow: auto; */!* } ``` Этот метод работает во всех браузерах, [edit src="winnie-clearfill-overflow"]полный код в песочнице[/edit]. Несмотря на внешнюю странность, этот способ не является "хаком". Такое поведение прописано в спецификации CSS. Однако, установка `overflow` может привести к появлению полосы прокрутки, способ с псевдоэлементом `:after` более безопасен. ## float вместо display:inline-block При помощи `float` можно размещать блочные элементы в строке, похоже на `display: inline-block`: [codetabs src="gallery-float" border="1" height=550 link edit] Стиль здесь: ```css .gallery li { float: left; width: 130px; list-style: none; } ``` Элементы `float:left` двигаются влево, а если это невозможно, то вниз, автоматически адаптируясь под ширину контейнера, получается эффект, аналогичный `display: inline-block`, но с особенностями `float`. ## Вёрстка в несколько колонок Свойство `float` позволяет делать несколько вертикальных колонок. ### float:left + float:right Например, для вёрстки в две колонки можно сделать два `
`. Первому указать `float:left` (левая колонка), а второму -- `float:right` (правая колонка). Чтобы они не ссорились, каждой колонке нужно дополнительно указать ширину: ```html
Шапка
Левая колонка
Правая колонка
``` Стили: ```css .column-left { float: left; width: 30%; } .column-right { float: left; width: 70%; } .footer { clear: both; } ``` Результат (добавлены краски): [codetabs src="two-columns" border="1" height=440] В эту структуру легко добавить больше колонок с разной шириной. Правой колонке можно было бы указать и `float:right`. ### float + margin Ещё вариант -- сделать `float` для левой колонки, а правую оставить в потоке, но с отбивкой через `margin`: ```css .column-left { float: left; width: 30%; } .column-right { margin-left: 30%; } .footer { clear: both; } ``` Результат (добавлены краски): [codetabs src="two-columns-2" border="1" height=440] В примере выше -- показана небольшая проблема. Колонки не растягиваются до одинаковой высоты. Конечно, это не имеет значения, если фон одинаковый, но что, если он разный? В современных браузерах (кроме IE10-) эту же задачу лучше решает flexbox. Для старых есть различные обходы и трюки, которые позволяют обойти проблему в ряде ситуаций, но они выходят за рамки нашего обсуждения. Если интересно -- посмотрите, например, [Faux Columns](http://goodline.spb.ru/III-05-002.html).