Свойство float в CSS занимает особенное место. До его появления расположить два блока один слева от другого можно было лишь при помощи таблиц. Но в его работе есть ряд особенностей. Поэтому его иногда не любят, но при их понимании float станет вашим верным другом и помощником.
Далее мы рассмотрим, как работает float, разберём решения сопутствующих проблем, а также ряд полезных рецептов.
Как работает float
Синтаксис:
float: left | right | none | inherit;При применении этого свойства происходит следующее:
- Элемент позиционируется как обычно, а затем вынимается из документапотока и сдвигается влево (дляleft) или вправо (дляright) до того как коснётся либо границы родителя, либо другого элемента сfloat.
- Если пространства по горизонтали не хватает для того, чтобы вместить элемент, то он сдвигается вниз до тех пор, пока не начнёт помещаться.
- Другие непозиционированные блочные элементы без floatведут себя так, как будто элемента сfloatнет, так как он убран из потока.
- Строки (inline-элементы), напротив, «знают» о floatи обтекают элемент по сторонам.
Ещё детали:
- 
Элемент при наличии floatполучаетdisplay:block.То есть, указав элементу, у которого display:inlineсвойствоfloat: left/right, мы автоматически сделаем его блочным. В частности, для него будут работатьwidth/height.Исключением являются некоторые редкие displayнаподобиеinline-tableиrun-in(см. Relationships between „display“, „position“, and „float“)
- 
Ширина float-блока определяется по содержимому. («CSS 2.1, 10.3.5»).
- 
Вертикальные отступы marginэлементов сfloatне сливаются с отступами соседей, в отличие от обычных блочных элементов.
Это пока только теория. Далее мы рассмотрим происходящее на примере.
Текст с картинками
Одно из первых применений float, для которого это свойство когда-то было придумано – это вёрстка текста с картинками, отжатыми влево или вправо.
Например, вот страница о Винни-Пухе с картинками, которым поставлено свойство float:
Её HTML-код выглядит примерно так:
<img src="1.jpg" style="float:right">
<p>Текст...</p>
<p>Текст...</p>
<img src="2.jpg" style="float:left">
<p>Текст...</p>
<img src="3.jpg" style="float:right">
<p>Текст...</p>Каждая картинка, у которой есть float, обрабатывается в точности по алгоритму, указанному выше.
Посмотрим, например, как выглядело бы начало текста без float:
- Элемент IMGвынимается издокументапотока. Иначе говоря, последующие блоки начинают вести себя так, как будто его нет, и заполняют освободившееся место (изображение для наглядности полупрозрачно):
- Элемент IMGсдвигается максимально вправо(приfloat:right):
- Строки, в отличие от блочных элементов, «чувствуют» floatи уступают ему место, обтекая картинку слева:
При float:left – всё то же самое, только IMG смещается влево (или не смещается, если он и так у левого края), а строки – обтекают справа
Строки и инлайн-элементы смещаются, чтобы уступить место float. Обычные блоки – ведут себя так, как будто элемента нет.
Чтобы это увидеть, добавим параграфам фон и рамку, а также сделаем изображение немного прозрачным:
Как видно из рисунка, параграфы проходят «за» float. При этом строки в них о float'ах знают и обтекают их, поэтому соответствующая часть параграфа пуста.
Блок с float
Свойство float можно поставить любому элементу, не обязательно картинке. При этом элемент станет блочным.
Посмотрим, как это работает, на конкретной задаче – сделать рамку с названием вокруг картинки с Винни.
HTML будет такой:
<h2>Винни-Пух</h2>
<div class="left-picture">
  <img src="winnie-mult.jpg" width="200" height="150">
  <div>Кадр из советского мультфильма</div>
</div>
<p>Текст...</p>…то есть, div.left-picture включает в себя картинку и заголовок к ней. Добавим стиль с float:
.left-picture {
  float: left;
  /* рамочка и отступ для красоты (не обязательно) */
  margin: 0 10px 5px 0;
  text-align: center;
  border: 1px solid black;
}Результат:
Заметим, что блок div.left-picture «обернул» картинку и текст под ней, а не растянулся на всю ширину. Это следствие того, что ширина блока с float определяется по содержимому.
Очистка под float
Разберём ещё одну особенность использования свойства float.
Для этого выведем персонажей из мультфильма «Винни-Пух». Цель:
Реализуем её, шаг за шагом.
Шаг 1. Добавляем информацию
Попробуем просто добавить Сову после Винни-Пуха:
<h2>Винни-Пух</h2>
<div class="left">Картинка</div>
<p>..Текст о Винни..</p>
<h2>Сова</h2>
<div class="left">Картинка</div>
<p>..Текст о Сове..</p>Результат такого кода будет странным, но предсказуемым:
Произошло следующее:
- Заголовок <h2>Сова</h2>не заметилfloat(он же блочный элемент) и расположился сразу после предыдущего параграфа<p>..Текст о Винни..</p>.
- После него идёт float-элемент – картинка «Сова». Он был сдвинут влево. Согласно алгоритму, он двигается до левой границы или до касания с другимfloat-элементом, что и произошло (картинка «Винни-Пух»).
- Так как у совы float:left, то последующий текст обтекает её справа.
Шаг 2. Свойство clear
Мы, конечно же, хотели бы расположить заголовок «Сова» и остальную информацию ниже Винни-Пуха.
Для решения возникшей проблемы придумано свойство clear.
Синтаксис:
clear: left | right | both;Применение этого свойства сдвигает элемент вниз до тех пор, пока не закончатся  float'ы слева/справа/с обеих сторон.
Применим его к заголовку H2:
h2 {
  clear: left;
}Результат получившегося кода будет ближе к цели, но всё ещё не идеален:
Элементы теперь в нужном порядке. Но куда пропал отступ margin-top у заголовка «Сова»?
Теперь заголовок «Сова» прилегает снизу почти вплотную к картинке, с учётом её margin-bottom, но без своего большого отступа margin-top.
Таково поведение свойства clear. Оно сдвинуло элемент h2 вниз ровно настолько, чтобы элементов float не было сбоку от его верхней границы.
Если посмотреть на элемент заголовка внимательно в инструментах разработчика, то можно заметить отступ margin-top у заголовка по-прежнему есть, но он располагается «за» элементом float и не учитывается при работе в clear.
Чтобы исправить ситуацию, можно добавить перед заголовком пустой промежуточный элемент без отступов, с единственным свойством clear:both. Тогда уже под ним отступ заголовка будет работать нормально:
<h2>Винни-Пух</h2>
<div class="left">Картинка</div>
<p>Текст</p>
<div style="clear:both"></div>
<h2>Сова</h2>
<div class="left">Картинка</div>
<p>Текст</p>Результат получившегося кода:
- Свойство clearгарантировало, что<div style="clear:both">будет под картинкой сfloat.
- Заголовок <h2>Сова</h2>идёт после этого<div>. Так что его отступ учитывается.
Заполнение блока-родителя
Итак, мы научились располагать другие элементы под float. Теперь рассмотрим следующую особенность.
Из-за того, что блок с float удалён из потока, родитель не выделяет под него места.
Например, выделим для информации о Винни-Пухе красивый элемент-контейнер <div class="hero">:
<div class="hero">
  <h2>Винни-Пух</h2>
  <div class="left">Картинка</div>
  <p>Текст.</p>
</div>Стиль контейнера:
.hero {
  background: #D2B48C;
  border: 1px solid red;
}Результат получившегося кода:
Элемент с float оказался выпавшим за границу родителя .hero.
Чтобы этого не происходило, используют одну из следующих техник.
Поставить родителю float
Элемент с float обязан расшириться, чтобы вместить вложенные float.
Поэтому, если это допустимо, то установка float контейнеру всё исправит:
.hero {
  background: #D2B48C;
  border: 1px solid red;
  float: left;
}Разумеется, не всегда можно поставить родителю float, так что смотрим дальше.
Добавить в родителя элемент с clear
Добавим элемент div style="clear:both" в самый конец контейнера .hero.
Он с одной стороны будет «нормальным» элементом, в потоке, и контейнер будет обязан выделить под него пространство, с другой – он знает о float и сместится вниз.
Соответственно, и контейнер вырастет в размере:
<div class="hero">
  <h2>Винни-Пух</h2>
  <div class="left">Картинка</div>
  <p>Текст.</p>
  <div style="clear:both"></div>
</div>Результат – правильное отображение, как и в примере выше. Открыть код.
Единственный недостаток этого метода – лишний HTML-элемент в разметке.
Универсальный класс clearfix
Чтобы не добавлять в HTML-код лишний элемент, можно задать его через :after.
.clearfix:after {
  content: "."; /* добавить содержимое: "." */
  display: block;  /* сделать блоком, т.к. inline не может иметь clear */
  clear: both;  /* с обеих сторон clear */
  visibility: hidden; /* сделать невидимым, зачем нам точка внизу? */
  height: 0;  /* сделать высоту 0, чтобы не занимал место */
}Добавив этот класс к родителю, получим тот же результат, что и выше. Открыть код.
overflow:auto/hidden
Если добавить родителю overflow: hidden или overflow: auto, то всё станет хорошо.
.hero {
  overflow: auto;
}Этот метод работает во всех браузерах, полный код в песочнице.
Несмотря на внешнюю странность, этот способ не является «хаком». Такое поведение прописано в спецификации CSS.
Однако, установка overflow может привести к появлению полосы прокрутки, способ с псевдоэлементом :after более безопасен.
float вместо display:inline-block
При помощи float можно размещать блочные элементы в строке, похоже на display: inline-block:
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <style>
    .gallery li {
      float: left;
      width: 130px;
      list-style: none;
      /* красивости */
      border: 1px solid black;
      text-align: center;
      margin: 5px;
    }
  </style>
</head>
<body>
  <ul class="gallery">
    <li>
      <img src="https://js.cx/carousel/1.png" width="130" height="130">
      <div>Картинка 1</div>
    </li>
    <li>
      <img src="https://js.cx/carousel/2.png" width="130" height="130">
      <div>Картинка 2</div>
    </li>
    <li>
      <img src="https://js.cx/carousel/3.png" width="130" height="130">
      <div>Картинка 3</div>
    </li>
    <li>
      <img src="https://js.cx/carousel/4.png" width="130" height="130">
      <div>Картинка 4</div>
    </li>
    <li>
      <img src="https://js.cx/carousel/5.png" width="130" height="130">
      <div>Картинка 5</div>
    </li>
    <li>
      <img src="https://js.cx/carousel/6.png" width="130" height="130">
      <div>Картинка 6</div>
    </li>
    <li>
      <img src="https://js.cx/carousel/7.png" width="130" height="130">
      <div>Картинка 7</div>
    </li>
    <li>
      <img src="https://js.cx/carousel/8.png" width="130" height="130">
      <div>Картинка 8</div>
    </li>
    <li>
      <img src="https://js.cx/carousel/9.png" width="130" height="130">
      <div>Картинка 9</div>
    </li>
  </ul>
</body>
</html>Стиль здесь:
.gallery li {
  float: left;
  width: 130px;
  list-style: none;
}Элементы float:left двигаются влево, а если это невозможно, то вниз, автоматически адаптируясь под ширину контейнера, получается эффект, аналогичный display: inline-block, но с особенностями float.
Вёрстка в несколько колонок
Свойство float позволяет делать несколько вертикальных колонок.
float:left + float:right
Например, для вёрстки в две колонки можно сделать два <div>. Первому указать float:left (левая колонка), а второму – float:right (правая колонка).
Чтобы они не ссорились, каждой колонке нужно дополнительно указать ширину:
<div>Шапка</div>
<div class="column-left">Левая колонка</div>
<div class="column-right">Правая колонка</div>
<div class="footer">Низ</div>Стили:
.column-left {
  float: left;
  width: 30%;
}
.column-right {
  float: left;
  width: 70%;
}
.footer {
  clear: both;
}Результат (добавлены краски):
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <style>
    body,
    html {
      margin: 0;
      padding: 0;
    }
    .column-left {
      float: left;
      width: 30%;
    }
    .column-right {
      float: left;
      width: 70%;
      overflow: auto;
      /* расшириться вниз захватить float'ы */
    }
    .footer {
      clear: both;
    }
    .inner {
      margin: 1em;
    }
  </style>
</head>
<body>
  <div style="background:yellow">Шапка</div>
  <div class="column-left" style="background:#aef">
    <div class="inner">
      <!-- див для отступа внутри ширины родителя -->
      <h3>Персонажи:</h3>
      <ul>
        <li>Винни-Пух</li>
        <li>Ослик Иа</li>
        <li>Сова</li>
        <li>Кролик</li>
      </ul>
    </div>
  </div>
  <div class="column-right" style="background:tan">
    <div class="inner">
      <h3>Винни-Пух</h3>
      <img src="https://js.cx/clipart/winnie-mult.jpg" style="float:left; margin: 0 1em .5em 0">
      <p>Ви́нни-Пу́х (англ. Winnie-the-Pooh) — плюшевый мишка, персонаж повестей и стихов Алана Александра Милна (цикл не имеет общего названия и обычно тоже называется «Винни-Пух», по первой книге). Один из самых известных героев детской литературы XX века.</p>
      <p>В 1960-е—1970-е годы, благодаря пересказу Бориса Заходера «Винни-Пух и все-все-все», а затем и фильмам студии «Союзмультфильм», где мишку озвучивал Евгений Леонов, Винни-Пух стал очень популярен и в Советском Союзе.</p>
    </div>
  </div>
  <div class="footer" style="background:yellow">Низ</div>
</body>
</html>В эту структуру легко добавить больше колонок с разной шириной. Правой колонке можно было бы указать и float:right.
float + margin
Ещё вариант – сделать float для левой колонки, а правую оставить в потоке, но с отбивкой через margin:
.column-left {
  float: left;
  width: 30%;
}
.column-right {
  margin-left: 30%;
}
.footer {
  clear: both;
}Результат (добавлены краски):
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <style>
    body,
    html {
      margin: 0;
      padding: 0;
    }
    .column-left {
      float: left;
      width: 30%;
    }
    .column-right {
      margin-left: 30%;
      width: 70%;
      overflow: auto;
      /* расшириться вниз захватить float'ы */
    }
    .footer {
      clear: both;
    }
    .inner {
      margin: 1em;
    }
  </style>
</head>
<body>
  <div style="background:yellow">Шапка</div>
  <div class="column-left" style="background:#aef">
    <div class="inner">
      <!-- див для отступа внутри ширины родителя -->
      <h3>Персонажи:</h3>
      <ul>
        <li>Винни-Пух</li>
        <li>Ослик Иа</li>
        <li>Сова</li>
        <li>Кролик</li>
      </ul>
    </div>
  </div>
  <div class="column-right" style="background:tan">
    <div class="inner">
      <h3>Винни-Пух</h3>
      <img src="https://js.cx/clipart/winnie-mult.jpg" style="float:left; margin: 0 1em .5em 0">
      <p>Ви́нни-Пу́х (англ. Winnie-the-Pooh) — плюшевый мишка, персонаж повестей и стихов Алана Александра Милна (цикл не имеет общего названия и обычно тоже называется «Винни-Пух», по первой книге). Один из самых известных героев детской литературы XX века.</p>
      <p>В 1960-е—1970-е годы, благодаря пересказу Бориса Заходера «Винни-Пух и все-все-все», а затем и фильмам студии «Союзмультфильм», где мишку озвучивал Евгений Леонов, Винни-Пух стал очень популярен и в Советском Союзе.</p>
    </div>
  </div>
  <div class="footer" style="background:yellow">Низ</div>
</body>
</html>В примере выше – показана небольшая проблема. Колонки не растягиваются до одинаковой высоты. Конечно, это не имеет значения, если фон одинаковый, но что, если он разный?
В современных браузерах (кроме IE10-) эту же задачу лучше решает flexbox.
Для старых есть различные обходы и трюки, которые позволяют обойти проблему в ряде ситуаций, но они выходят за рамки нашего обсуждения.
Комментарии
<code>, для нескольких строк кода — тег<pre>, если больше 10 строк — ссылку на песочницу (plnkr, JSBin, codepen…)