Самое сложное в этой заметке — придумать для нее название, не представляю как можно перевести clearing floats, не чистка же. А посвящена она до безобразия простому методу этого клиринга, хоть он и достаточно стар, возможно, кто-то еще не знает, к примеру, я не знал.

У читателей полных RSS, примеры к этой статье скорее всего будут искажены ридером, поэтому за примерами прошу проследовать на сайт.

Проблема

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

К примеру, у нас есть такой код:

div.container {
    border: 1px solid #000000;
}

div.left {
    width: 45%;
    float: left;
}

div.right {
    width: 45%;
    float: right;
}

И соответствующий ему результат:

Левая колонка.

Левая колонка.

Левая колонка.

Левая колонка.

Правая колонка.

Правая колонка.

Правая колонка.

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

Традиционное решение

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

Левая колонка.

Левая колонка.

Левая колонка.

Левая колонка.

Правая колонка.

Правая колонка.

Правая колонка.

div с включенным clear: both

Дополнительный элемент можно добавить как в самом коде так и с помощью псевдо-класса :after (поскольку IE не поддерживает :after этот вариант представляет только теоретический интерес).

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

Новое решение

Алекс Волкер, опубликовавший это решение впервые, упоминает, что идея принадлежит Паулю О`Брайну. Но, кто бы не придумал это решение, выглядит оно так:

div.container {
    border: 1px solid #000000;
    overflow: auto;
    width: 100%
}

Свойство width используется, чтобы включить hasLayout в IE Win (кроме IE7), работает это превосходно:

Левая колонка.

Левая колонка.

Левая колонка.

Левая колонка.

Правая колонка.

Правая колонка.

Правая колонка.

Теперь граница охватывает плавающие элементы.

Сложности

Некоторые моменты требуют особого внимания:

  1. Трюк работает с тремя из четырех возможных значений overflow: auto, hidden, scroll. Но в последнем случае будут видны скроллбары.
  2. Некоторые браузеры требуют, чтобы для контейнера было установлено свойство width или height.
  3. Браузер может показывать скроллбар если контент выходит за пределы ширины контейнера.

Необходимость width или height

Чтобы прием сработал в Opera или IE Win нужно использовать width или height. В противном случае IE не будет растягивать блок, чтобы поглотить плавающие элементы, а Opera, того хуже, полностью скроет содержимое контейнера.

Чаще всего подойдет значение width: 100%, но для сложной разметки могут потребоваться другие значения.

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

Explorer Mac: hidden

Если для вас важна поддержка IE Mac, используйте overflow: hidden, при использовании overflow: auto этот браузер почему-то постоянно отображает скроллбары.

Нежелательные скроллбары

Dave Shea, обращает внимание на то, что если контент не вмещается в контейнер по ширине, появляются нежелательные скроллбары. Лично меня удивляет, то что это считается серьезной проблемой. Используйте overflow: hidden если хотите обезопасить себя от скроллбаров. Конечно, это может привести к тому, что, выходящая за пределы контейнера, часть контента будет скрыта, но если мы будем:

  1. оставлять автоматической высоту контейнера (т.е. столько сколько потребуется),
  2. делать ширину плавающих блоков меньше ширины контейнера,

столкнуться с этой проблемой, скорее всего не придется.

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

Окончательное решение

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

div.container {
    border: 1px solid #000000;
    overflow: hidden;
    width: 100%;
}

div.left {
    width: 45%;
    float: left;
}

div.right {
    width: 45%;
    float: right;
}

Левая колонка.

Левая колонка.

Левая колонка.

Левая колонка.

Правая колонка.

Правая колонка.

Правая колонка.

Вот такое, предельно простое и красивое решение.

Еще более красивое решение

В предыдущем примере используется width: 100% (или другая подходящая ширина), понятное дело, что это не всегда удобно, да и не всегда возможно. Вадим Макеев подсказывает, что включить hasLayout для IE5.5-6 можно с помощью zoom: 1, тогда окончательно решение будет выглядеть так:

div.container {
    border: 1px solid #000000;
    overflow: hidden;
    zoom: 1;
}

div.left {
    width: 45%;
    float: left;
}

div.right {
    width: 45%;
    float: right;
}

Левая колонка.

Левая колонка.

Левая колонка.

Левая колонка.

Правая колонка.

Правая колонка.

Правая колонка.

Применять его гораздо проще, поскольку не нужно задумываться о том, какую ширину задать элементу, и как быть с отступами.

zoom: 1 можно спрятать в условный коммент, или в отдельный файл для IE и ждать пока отомрет 6-я версия. Пока есть невалидный браузер, приходится использовать и невалидный код.

Вместо zoom: 1, можно попробовать:

div.container {
    overflow: hidden;
}

* html div.container {
    overflow: visible;
    height:1%;
}

Валидатор подвоха не заметит, но это все таки хак.

Можно попробовать:

div.container {
    overflow: hidden;
    display:inline-block;
}

div.container {
    display:block;
}

Похожие статьи