Вмещение float-элементов

Недавно столкнулся с достаточно неприятной проблемой - при использовании свойств float в дочерних div’ах, они не растягивают по вертикали размер родительских элементов, и как бы "перекрывают" их. Оказывается, проблема достаточно тривиальная и возникла у меня только из-за отсутствия опыта верстальщика, вскоре я нашел решение в заметке, которую с удовольствием переведу на русский.

Оригинал статьи: http://gtwebdev.com/workshop/floats/enclosing-floats.php

Перевод:

Новички в CSS, а так же те, кто раньше работал преимущественно в IE, зашли в тупик с неприятным "багом" в Firefox и других современных браузерах. Фон исчезает, или рамка - но в IE все хорошо (прим. переводчика: откровенно говоря, мне ооочень странно слышать что-то подобное, честно =)). А верстальщики кусают локти.

Для такого поведения есть свои причины, и здесь IE опять облажался. Причиной всему баг, известный по имени "hasLayout". Не будем детально на этом останавливаться.  Лучшая документация была написана Ingo Chao (http://www.satzansatz.de/cssd/onhavinglayout.html) Рекомендую почитать эту статью. (От переводчика: hasLayout - это "костыльное" свойство IE, в других браузерах его нету. Напрямую задать свойство через стили невозможно, потому что оно разрабатывалось для внутренних целей, фактически в CSS его нет.)

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

IE7 исправил многие IE6 баги. IE8 убил hasLayout и расширил поддержку CSS2.1

float по умолчанию

Обратите внимание, что в первом блоке float элемент расширяется вне границ родительского div. Это нормальное поведение. Во втором блоке родителю задана ширина. Это задает проприетарному IE свойству, hasLayout, значение true. Если true, IE ошибочно ограничивает float (см. пример).

С другой стороны, IE некорректно обрабатывает коллапсированы margin`ы когда у элемента есть layout. Margin`ы нельзя коллапсировать, когда в элемента есть padding или borders, или если это - float-элемент. В терминах IE, у float всегда есть layout. Вы можете увидеть, что float-элемент коллапсирует в обеих случаях, а non-float margin коллапсирует в размер родителя.

fl1Использование свойства overflow

Если у родительского элемента есть overflow значение другое, чем дефолтное "visible", высота элемента будет подогнана так, чтобы вместить дочерние float’ы.

Обратите внимание, что IE <= 6 не следует правилу. В IE будет работать, если родительскому єлементу задать ширину. Это связано с тем, что элементы с размером в IE расширяются, чтобы вложить контент. IE7 добавил {overflow: hidden || auto;} в список свойств, которые включают hasLayout.

fl2Использование свойства display

Таблицы и их ячейки автоматически вмещают их контент. Даже если высота задается, она понимается как минимальная. Сделать элемент табличным можно так: {display: table;} or {display: table-cell;}Обратите также внимание, что таблицы и ячейки "оборачивают" контент.

Еще один пример того, что IE не следует спецификациям, и чтобы и IE, и современные браузеры отображали страницу одинаково, надо задавать ширину.

Table-cell элемент  - достаточно трудоемкое решение в плане кроссбраузерности, так как это inline-элемент, который нелегко адаптировать под IE.

Обратите внимание, что в современных браузерах у ячеек нету свойства margin. Используйте {border-spacing: length [length];}.

Inline-block элементы работают в современных браузерах так же, как и в IE < 8. В старых IE, hasLayout включенный, а в новых браузерах установлено новое форматирование блоков.

IE < 8 не поддерживает inline-block в не-inline элементов. Firefox 2 использует экспериментальный параметр -moz-inline-box.

fl3fl4Использование float-родителя

Float-элемент будет вмещать свои дочерние элементы. Float без размеров будет под размер содержимого. Если вы этого не хотите, можете задать размер.

fl5Чтобы следующие элемент был перед контейнером, надо сделать ему clear.

Использование Tony Aslett в Clearfix Hack

Это очень элегантный подход к очистке float. Он использует :after псевдоксласс чтобы сделать clear: перед закрытием родительского элемента. Это заставляет родителя вместить float-элементы. Подробней тут или тут.

Обратите внимание, что IE коллапсирует и float, и родительский элемент. Это потому, что родитель, в IE, получает hasLayout, и поэтому он вложит float.

fl6О чем это все?

Вы скажете: "IE не нужно все это, зачем весь этот шум?" Это правда. Пока родитель вашего float-элемента имеет размер, он будет автоматически содержать все содержимое. Звучит неплохо, пока у вас элементы с размером.

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

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