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 #
Максим, ваши обвинения абсолютно бессмысленны, я ежемесячно (ну почти) публикую обзоры по русским ресурсам, при этом вполне очевидно, что уследить за блогами всех русских разработчиков я не могу.