Clear для плавающих блоков
Peter-Paul Koch, 20 апреля 2008
Самое сложное в этой заметке — придумать для нее название, не представляю как можно перевести clearing floats, не чистка же. А посвящена она до безобразия простому методу этого клиринга, хоть он и достаточно стар, возможно, кто-то еще не знает, к примеру, я не знал.
У читателей полных RSS, примеры к этой статье скорее всего будут искажены ридером, поэтому за примерами прошу проследовать на сайт.
Проблема
При верстке часто встает задача, натянуть родительский блок на плавающий:
К примеру, у нас есть такой код:
div.container {
border: 1px solid #000000;
}
div.left {
width: 45%;
float: left;
}
div.right {
width: 45%;
float: right;
}
И соответствующий ему результат:
Левая колонка.
Левая колонка.
Левая колонка.
Левая колонка.
Правая колонка.
Правая колонка.
Правая колонка.
Мы хотели, чтобы оба блока были обведены черной границей, но поскольку родительский блок не имеет высоты, а просто содержит плавающие блоки, все, что мы видим — это граница над плавающими блоками.
Традиционное решение
Обычно для решения этой проблемы использовался дополнительный элемент, с установленным clear: both. Благодаря наличию не плавающего элемента родительский контейнер растягивался чтобы поглотить его.
Левая колонка.
Левая колонка.
Левая колонка.
Левая колонка.
Правая колонка.
Правая колонка.
Правая колонка.
clear: both
Дополнительный элемент можно добавить как в самом коде так и с помощью псевдо-класса :after (поскольку IE не поддерживает :after этот вариант представляет только теоретический интерес).
В любом случае решение не очень красивое, ведь мы стремимся использовать только семантические элементы, избегая создания элементов только для оформления. К несчастью, до недавнего времени проблему можно было решить только так.
Новое решение
Алекс Волкер, опубликовавший это решение впервые, упоминает, что идея принадлежит Паулю О`Брайну. Но, кто бы не придумал это решение, выглядит оно так:
div.container {
border: 1px solid #000000;
overflow: auto;
width: 100%
}
Свойство width используется, чтобы включить hasLayout в IE Win (кроме IE7), работает это превосходно:
Левая колонка.
Левая колонка.
Левая колонка.
Левая колонка.
Правая колонка.
Правая колонка.
Правая колонка.
Теперь граница охватывает плавающие элементы.
Сложности
Некоторые моменты требуют особого внимания:
- Трюк работает с тремя из четырех возможных значений
overflow:auto,hidden,scroll. Но в последнем случае будут видны скроллбары. - Некоторые браузеры требуют, чтобы для контейнера было установлено свойство
widthилиheight. - Браузер может показывать скроллбар если контент выходит за пределы ширины контейнера.
Необходимость 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 если хотите обезопасить себя от скроллбаров. Конечно, это может привести к тому, что, выходящая за пределы контейнера, часть контента будет скрыта, но если мы будем:
- оставлять автоматической высоту контейнера (т.е. столько сколько потребуется),
- делать ширину плавающих блоков меньше ширины контейнера,
столкнуться с этой проблемой, скорее всего не придется.
С другой стороны, никогда не говори никогда. В тестах все работает замечательно но на реальных сайтах, очень много элементов и стилей, можно запутаться и что-то пойдет не так как задумано.
Окончательное решение
Проанализировав проблемы, мы остановимся следующем коде:
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;
} 
















andead 20 апреля, 2008 3:54 #
раньше пользовался похожим способом http://0range.ru/?p=4
но теперь буду применять ваш :)
s_light 20 апреля, 2008 9:48 #
Все предельно просто и результат отличный. Раньше пользовалась элементом div со свойством clear: both.... А все можно сделать гораздо проще!
Кстати, о названии. Думаю, всем, кто занимается веб-дизайном привычнее выражение "очистка" плавающих блоков... не "клиринг" :)
Клиринг - это все-таки из области финансов, - система расчетов между банками, кто не знает. Название в rss меня поначалу даже смутило - не сразу поняла о чем статья. Оказалось, о такой насущной проблеме, как очистка... =)
pepelsbey 20 апреля, 2008 10:14 #
Всё бы хорошо, но статейке уже три года — тогда ещё был IE for Mac и не было IE7 ;) Да и решение со 100% шириной годится далеко не во всех случаях.
Гораздо более универсальное решение — overflow:hidden (для нормальных браузеров и IE7+) плюс zoom:1 (IE5.5-6)
donquijote 20 апреля, 2008 11:12 #
Я всегда пользуюсь методом Тони Алсета, практическое применение псевдо-класса :after :
.clearfix:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.clearfix {display: inline-block;}
* html .clearfix {height: 1%;}
.clearfix {display: block;}
Просто добавляю в родительский див class="clearfix" и все.
Евгений 20 апреля, 2008 11:21 #
s_light,
Вот уж не знаю, смысл данного действия, далек от "очистки", но если это общепринятая терминология то готов сменить название.
Насколько я знаю, клиринг это система взаимозачетов между банками, позволяющая уменьшить перечисляемые суммы, но я про это даже не вспомнил, контекст не тот.
pepelsbey,
Ну IE7 как раз таки упоминается, а что статья не новая это я сразу отметил.
Вот уж точно.
Спасибо, добавлю в статью. Хотя, конечно, мне следовало погуглить перед тем как переводить, но так уж вышло :)
yopopt 20 апреля, 2008 12:38 #
Хм, а я думал что это вполне обычное решение. Всегда им пользовался за исключением случаев, когда удобней просто добавить следующему блоку clear: both;.
kuindzi 20 апреля, 2008 13:57 #
Ага, метод хороший. Берем на вооружение.
Муркт 20 апреля, 2008 20:24 #
Иван Сагалаев об этом способе написал давным-давно. Года полтора-два тому, если не раньше.
nicothin 21 апреля, 2008 1:32 #
последствия одного топика на хабре.
невалидный код назван "еще более красивым"...
Евгений 21 апреля, 2008 3:02 #
nicothin, высказывайте, пожалуйста, свои предложения.
1)
zoom: 1можно спрятать в условный коммент, или в отдельный файл для IE и ждать пока отомрет 6-я версия. Пока есть невалидный браузер, приходится использовать и невалидный код.2) Вместо
zoom: 1, можно попробовать:валидатор подвоха не заметит, но это все таки хак.
3) Можно попробовать:
еще более красивое решение :)
donquijote,
.clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } .clearfix {display: inline-block;} * html .clearfix {height: 1%;} .clearfix {display: block;}у меня такие аргументы против вашего решения:
все браузеры поддерживающие :after удовлетворятся всего одним свойством
overflow: hidden;из чего следует, что возня с :after не имеет смысла. Дальше идет overkill делаем hasLayout двумя методами сразу, зачем?donquijote 21 апреля, 2008 11:18 #
Вернее было бы написать так:
Все это возня с IE/Mac (добавление display:inline-block), конечно же если он вам не нужен, а это скорее всего так, можно оставить только * html .clearfix {height: 1%;}
Подробнее здесь http://www.positioniseverything.net/easyclearing.html
Евгений 21 апреля, 2008 12:59 #
А в IE/Mac
display: inline-block;не дает хронического hasLayout?И все-таки, потестируйте пример метода (3) из моего предыдущего коммента, не будет ли так проще, работает в FF2, Opera 9.10, IE5.5-6-7-8b1, Safari 3.0.3, на остальном не тестил, чуть позже поэкспериментирую на сайте.
arestov 22 апреля, 2008 11:28 #
в css нет свойства zoom. значит хак.
использование height в процентах правильней, и это не хак, потому что процентная задача высоты обсчитывается только если у контейнера задана высота в неотносительных единицах (пикселах, например), в проивном слуае height:1% просто игнорируется
Евгений 22 апреля, 2008 14:53 #
Можно, конечно, и
height: 1%только есть потенциальная опасность, что вся конструкция попадет в блок сheight(хоть вероятность и не велика) и свернется в однопроцентную трубочку.overflow: hiddenв таком случае выглядит весьма издевательски.IE6 достаточно и относительных единиц.
zlodie 23 апреля, 2008 11:13 #
Клиринг плавающих блоков = Сброс обтекания?
Евгений 23 апреля, 2008 11:41 #
Растягивание родителького блока, чтобы он полностью поглощал плавающий, en — Clearing floats, приемлемой русской альтернативы, я не знаю.
kocten 23 апреля, 2008 13:40 #
Метод неплох, прост, интересен и наверняка может иметь широкое применение. А вот метод donquijote помоему излишне усложнен, хаки - это вапще фи, тем более когда есть более правильное решение проблемы.
На счет названия: ничего точно сказать не могу, но если просто задуматься над дословным переводом "Очистка плаванья(или поплавков)" наводит на мысль, что Clearing floats значит "очистка от поплавков". С точки зрения браузера это фактически превращение ранее плавающих блоков в статичные, это подходит под фразу "очистка от поплавков". Но врядли кому нибудь эта фраза окажется понятной, а по текущему названия я сразу догодался о чем именно речь, логичнее будет его оставить, чем искать более точный дословный перевод :)
azimsky 24 апреля, 2008 14:34 #
Clearing floats - очищаем плавающие блоки.
- "зачистка" плавающих блоков
А вообще "Clear для плавающих блоков тоже понятно"
djinn 27 апреля, 2008 10:51 #
Отличное решение. Раньше пользовался исключительно clear:both, а это решение действительно все меняет :) Огромное спасибо авторам!
Шильгия 3 мая, 2008 10:02 #
Евгений, спасибо.
Хоть лично для меня этот способ и не был новым, скорее — давно используемым, но как видно из комментариев, для многих он был открытием. А значит — благодаря этой статье чуть увеличится количество грамотных сайтов.
Вот только не слишком ли много уделяется внимания браузеру IE-Mac? Сколько доводилось мне встречать применение этого чуда программерской мысли — как правило маководы от нечего делать ставили его себе и соревновались, кто найдёт более криво отображаемый сайт :) Для реального просмотра сайтов его никто не использует как минимум года три. И в российской действительности даже на самых крупных порталах скорее всего не окажется ни одного посетителя с таким браузером.
Ну разве что разработчикам попонтоваться друг перед другом о том, что «моя вёрстка работает даже в IE-Mac» ;)
Заметки программиста» Архив блога » Воскресный рабочий день 4 мая, 2008 6:56 #
[...] о верстке, ориентирована на тех, кому clear:both надоел. Clear для пацанов. Да и кстати, сверстать можно действительно все, а [...]
Денис Талала 4 мая, 2008 16:08 #
Вы знаете, давно заметил (но всё забывал сказать), что при печати страниц сайта ссылки (их номера и список в конце) дублируются. То есть вместо 14-ой ссылки указана 1414, и в конце печатается аж 2 одинаковых списка. Нужно исправить. :)
Евгений 4 мая, 2008 22:22 #
Денис Талала, странно, у меня не наблюдается ничего подобного.
Денис Талала 5 мая, 2008 0:09 #
Я печатаю через Oper'у. Но больше ничего не дублируется, только ссылки. Вряд ли это ошибка браузера.
Евгений 5 мая, 2008 0:25 #
У меня и в опере не двоиться.
В сайдбаре раздел "Ошибки на сайте" не двоиться?
Денис Талала 5 мая, 2008 6:02 #
Нет, “ошибки” не двоятся.
Денис Талала 7 мая, 2008 19:41 #
Извините, поспешил с ответом. Вот: http://www.ljplus.ru/img4/r/3/r3lim3/errors.gif
Евгений 9 мая, 2008 11:08 #
Мне кажется, это глюк jQquery, для начала попробую обновить.
Dimon 14 мая, 2008 0:02 #
Оч полезная статья. Раньше использовал div c clear:both. Но этот способ куда лучше и универсальнее. Как раз то что нужно. Авторам огромное спасибо.
Максим Покровский 17 мая, 2008 16:12 #
Я понимаю, что ресурс сделал имя на переводах, но нельзя настолько недооценивать русских разработчиков. Почти такое же средство было использовано мной. http://pokrovskii.com/konteyner-dlya-float-blokov/
Уверен, что почти у всех более-менее известных авторов блогов посвещенных css и xhtml, найдется похожее решение.
Евгений 17 мая, 2008 17:42 #
Максим, ваши обвинения абсолютно бессмысленны, я ежемесячно (ну почти) публикую обзоры по русским ресурсам, при этом вполне очевидно, что уследить за блогами всех русских разработчиков я не могу.
sitediz 19 мая, 2008 14:42 #
Спасибо.. как раз то, что искал....
bontonweb 16 июня, 2008 13:19 #
А в некторых случаях можно использовать и такой простой способ как
<br clear="all" />.Просто, валидно и семантично.
Евгений 16 июня, 2008 15:20 #
bontonweb, это не валидно, если бы и было валидно, то как атрибут
clearможет быть семантичным, я не представляю.bontonweb 16 июня, 2008 15:34 #
Евгений, вот что пишет по этому поводу спецификация HTML 4
http://linux.yaroslavl.ru/docs/www/html/html401/text.html#edef-BR
"Элемент BR принудительно обрывает (оканчивает) текущую строку текста.
Для визуальных ПА атрибут clear может использоваться для определения того, как разметка, следующая после элемента BR, обтекает другие всплывающие влево или вправо объекты, или начинается внизу после этих объектов."
Евгений 16 июня, 2008 15:53 #
Это конечно, но в том же руководстве, жмите на ссылку clear и первое, что вы увидите это "Не рекомендуется".
Попробуйте проверить эту конструкция валидатором, используя любой Strict DOCTYPE, атрибут clear не валиден.
djinn 23 июня, 2008 14:30 #
Есть ли метод без overflow:hidden? Просто иногда нужно, чтобы контентная зона тянулась, допустим при большом размере вставленной картинки. В этом случае она обрезается...о_О