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;
}
раньше пользовался похожим способом http://0range.ru/?p=4
но теперь буду применять ваш :)
Все предельно просто и результат отличный. Раньше пользовалась элементом div со свойством clear: both.... А все можно сделать гораздо проще!
Кстати, о названии. Думаю, всем, кто занимается веб-дизайном привычнее выражение "очистка" плавающих блоков... не "клиринг" :)
Клиринг - это все-таки из области финансов, - система расчетов между банками, кто не знает. Название в rss меня поначалу даже смутило - не сразу поняла о чем статья. Оказалось, о такой насущной проблеме, как очистка... =)
Всё бы хорошо, но статейке уже три года — тогда ещё был IE for Mac и не было IE7 ;) Да и решение со 100% шириной годится далеко не во всех случаях.
Гораздо более универсальное решение — overflow:hidden (для нормальных браузеров и IE7+) плюс zoom:1 (IE5.5-6)
Я всегда пользуюсь методом Тони Алсета, практическое применение псевдо-класса :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" и все.
s_light,
Вот уж не знаю, смысл данного действия, далек от "очистки", но если это общепринятая терминология то готов сменить название.
Насколько я знаю, клиринг это система взаимозачетов между банками, позволяющая уменьшить перечисляемые суммы, но я про это даже не вспомнил, контекст не тот.
pepelsbey,
Ну IE7 как раз таки упоминается, а что статья не новая это я сразу отметил.
Вот уж точно.
Спасибо, добавлю в статью. Хотя, конечно, мне следовало погуглить перед тем как переводить, но так уж вышло :)
Хм, а я думал что это вполне обычное решение. Всегда им пользовался за исключением случаев, когда удобней просто добавить следующему блоку clear: both;.
Ага, метод хороший. Берем на вооружение.
Иван Сагалаев об этом способе написал давным-давно. Года полтора-два тому, если не раньше.
последствия одного топика на хабре.
невалидный код назван "еще более красивым"...
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 двумя методами сразу, зачем?Вернее было бы написать так:
Все это возня с IE/Mac (добавление display:inline-block), конечно же если он вам не нужен, а это скорее всего так, можно оставить только * html .clearfix {height: 1%;}
Подробнее здесь http://www.positioniseverything.net/easyclearing.html
А в IE/Mac
display: inline-block;не дает хронического hasLayout?И все-таки, потестируйте пример метода (3) из моего предыдущего коммента, не будет ли так проще, работает в FF2, Opera 9.10, IE5.5-6-7-8b1, Safari 3.0.3, на остальном не тестил, чуть позже поэкспериментирую на сайте.
в css нет свойства zoom. значит хак.
использование height в процентах правильней, и это не хак, потому что процентная задача высоты обсчитывается только если у контейнера задана высота в неотносительных единицах (пикселах, например), в проивном слуае height:1% просто игнорируется
Можно, конечно, и
height: 1%только есть потенциальная опасность, что вся конструкция попадет в блок сheight(хоть вероятность и не велика) и свернется в однопроцентную трубочку.overflow: hiddenв таком случае выглядит весьма издевательски.IE6 достаточно и относительных единиц.
Клиринг плавающих блоков = Сброс обтекания?
Растягивание родителького блока, чтобы он полностью поглощал плавающий, en — Clearing floats, приемлемой русской альтернативы, я не знаю.
Метод неплох, прост, интересен и наверняка может иметь широкое применение. А вот метод donquijote помоему излишне усложнен, хаки - это вапще фи, тем более когда есть более правильное решение проблемы.
На счет названия: ничего точно сказать не могу, но если просто задуматься над дословным переводом "Очистка плаванья(или поплавков)" наводит на мысль, что Clearing floats значит "очистка от поплавков". С точки зрения браузера это фактически превращение ранее плавающих блоков в статичные, это подходит под фразу "очистка от поплавков". Но врядли кому нибудь эта фраза окажется понятной, а по текущему названия я сразу догодался о чем именно речь, логичнее будет его оставить, чем искать более точный дословный перевод :)
Clearing floats - очищаем плавающие блоки.
- "зачистка" плавающих блоков
А вообще "Clear для плавающих блоков тоже понятно"
Отличное решение. Раньше пользовался исключительно clear:both, а это решение действительно все меняет :) Огромное спасибо авторам!
Евгений, спасибо.
Хоть лично для меня этот способ и не был новым, скорее — давно используемым, но как видно из комментариев, для многих он был открытием. А значит — благодаря этой статье чуть увеличится количество грамотных сайтов.
Вот только не слишком ли много уделяется внимания браузеру IE-Mac? Сколько доводилось мне встречать применение этого чуда программерской мысли — как правило маководы от нечего делать ставили его себе и соревновались, кто найдёт более криво отображаемый сайт :) Для реального просмотра сайтов его никто не использует как минимум года три. И в российской действительности даже на самых крупных порталах скорее всего не окажется ни одного посетителя с таким браузером.
Ну разве что разработчикам попонтоваться друг перед другом о том, что «моя вёрстка работает даже в IE-Mac» ;)
Вы знаете, давно заметил (но всё забывал сказать), что при печати страниц сайта ссылки (их номера и список в конце) дублируются. То есть вместо 14-ой ссылки указана 1414, и в конце печатается аж 2 одинаковых списка. Нужно исправить. :)
Денис Талала, странно, у меня не наблюдается ничего подобного.
Я печатаю через Oper'у. Но больше ничего не дублируется, только ссылки. Вряд ли это ошибка браузера.
У меня и в опере не двоиться.
В сайдбаре раздел "Ошибки на сайте" не двоиться?
Нет, “ошибки” не двоятся.
Извините, поспешил с ответом. Вот: http://www.ljplus.ru/img4/r/3/r3lim3/errors.gif
Мне кажется, это глюк jQquery, для начала попробую обновить.
Оч полезная статья. Раньше использовал div c clear:both. Но этот способ куда лучше и универсальнее. Как раз то что нужно. Авторам огромное спасибо.
Я понимаю, что ресурс сделал имя на переводах, но нельзя настолько недооценивать русских разработчиков. Почти такое же средство было использовано мной. http://pokrovskii.com/konteyner-dlya-float-blokov/
Уверен, что почти у всех более-менее известных авторов блогов посвещенных css и xhtml, найдется похожее решение.
Максим, ваши обвинения абсолютно бессмысленны, я ежемесячно (ну почти) публикую обзоры по русским ресурсам, при этом вполне очевидно, что уследить за блогами всех русских разработчиков я не могу.
Спасибо.. как раз то, что искал....
А в некторых случаях можно использовать и такой простой способ как
<br clear="all" />.Просто, валидно и семантично.
bontonweb, это не валидно, если бы и было валидно, то как атрибут
clearможет быть семантичным, я не представляю.Евгений, вот что пишет по этому поводу спецификация HTML 4
http://linux.yaroslavl.ru/docs/www/html/html401/text.html#edef-BR
"Элемент BR принудительно обрывает (оканчивает) текущую строку текста.
Для визуальных ПА атрибут clear может использоваться для определения того, как разметка, следующая после элемента BR, обтекает другие всплывающие влево или вправо объекты, или начинается внизу после этих объектов."
Это конечно, но в том же руководстве, жмите на ссылку clear и первое, что вы увидите это "Не рекомендуется".
Попробуйте проверить эту конструкция валидатором, используя любой Strict DOCTYPE, атрибут clear не валиден.
Есть ли метод без overflow:hidden? Просто иногда нужно, чтобы контентная зона тянулась, допустим при большом размере вставленной картинки. В этом случае она обрезается...о_О
Супер, беру себе на заметку это решение. Сам же всегда пользовался clear: both
Супер, спасибо. Хорошее решение. Всегда думал как это сделать!
хороший метод, но у ФФ 2-го поколение вечно с ним проблемы небольшие вылезали именно из-за overflow: hidden; особенности в таком блоке находятся поля формы, текст при клике с слева от такого контейнера выделяется сразу в двух колонках (
display: inline-block; понимает Опера и сужает его.
Достойного решения пока нет, приходится все время верстать "по обстоятельствам".
я тоже сначала так думал, но когда один из клиентов потребовал точного совпадения экранной версии и версии для печати (я об этом писал на вебмасконе), оказалось, что при использовании overflow:hidden на печати блоки режутся по нижней границе страницы (не переносятся на следующую), пришлось переделывать под решение с :after
с этих самых пор пользуюсь только :after =)