Итак, долгожданная статья. Вопреки заголовку свойства display:float здесь не используется, что не отменяет результата.
Неделю назад мне потребовался эффект для создания плавающих блоков фиксированной ширины, примерно как на картинке:
Если вы пробовали верстать что-то похожее, то знаете в чём подвох.
В общем случае, сверстать этот макет было бы плёвым делом. Фиксированная ширина, фиксированная высота, float:left
и готово. Но! Дизайн требует чтобы количество контента могло варьироваться, что означает — если в одном из блоков будет больше контента, то вёрстка поедет
:
Так как первый блок выше чем другие, пятый блок, обтекает его слева, вместо того чтобы быть ниже. Я потратила немало времени в поисках нужной реализации, и в конце концов вспомнила про свойство display:inline-block
, кроссбраузерную реализацию которого, как оказывается, я ровно год назад утянула себе в закладочки. Далее — перевод этой статьи.
Начнём с простой страницы, с не сортированным списком, и установим свойство отображения display:inline-block
. Желательно использовать изначально блоковый элемент, такой как <li> для этих целей, т.к. в некоторых браузерах перевод из inline в inline-block работает некорректно.
<ul> <li> <h4>This is awesome</h4> <img src="http://farm4.static.flickr.com/3623/3279671785_d1f2e665b6_s.jpg" alt="lobster" width="75" height="75"/> </li> ... <ul>
<style> li { width: 200px; min-height: 250px; border: 1px solid #000; display: inline-block; margin: 5px; } </style>
Это выглядит неплохо в Firefox 3, Safari 3 и Опере:
Легко заметить, что что-то не так с вертикальным выравниванием (статью о котором я написала недавно, см. ссылку). Точнее не совсем не так, потому что это правильное отображение, но не то что мы хотели.
Выравнивание здесь проходит по базовой линии каждого элемента <li> относительно родителя <ul>. Что такое базовая линия можно увидеть на картинке:
Говоря проще значением по умолчанию для vertical-align в режиме inline или inline-block элемента, является базовая линия, что означает что базовая линия элемента будет расположена также как у родительского. Базовая линия в нашем случае показана на следующем изображении:
В любом случае, чтобы поправить это нам нужно просто указать vertical-align:top
, что приведёт к нужному расположению элементов:
За исключением конечно любимых всеми
IE 6 и 7, и Firefox 2.
Начнём с Firefox 2.
Firefox 2 не поддерживает inline-block
, но он поддерживает браузеро-специфичное свойство ‘-moz-inline-stack
’, которое даёт результат как раз как inline-block. И когда мы добавим после него свойство display:inline-block
, FF2 проигнорирует неизвестное свойство и оставит -moz-inline-stack, потому что он не поддерживает inline-block. Браузеры которые поддерживают inline-block будут использовать его, и проигнорируют предыдущее свойство.
<style> li { width: 200px; min-height: 250px; border: 1px solid #000; display: -moz-inline-stack; display: inline-block; vertical-align: top; margin: 5px; } </style>
(Не путайте также свойство ‘-moz-inline-stack’ с ‘-moz-inline-box’ обсуждаемым в тематическом топике на хабре, это разные вещи).
К сожалению в отображении небольшой баг:
Чтобы исправить его нужно просто обернуть всё что находится внутри <li> в <div>.
<li> <div> <h4>This is awesome</h4> <img src="http://farm4.static.flickr.com/3623/3279671785_d1f2e665b6_s.jpg" alt="lobster" width="75" height="75"/> </div> </li>
Это поправит всё внутри <li> и заставит их отображаться нормально.
Теперь разберёмся с IE 7. IE 7 тоже не поддерживает inline-block, но мы можем заставить его отображать <li> как если бы он был строчно-блоковым. Как? hasLayout
, волшебное свойство IE которое позволяет всё веселье! Вы не можете задать hasLayout
элементу объявлением hasLayout:true; или чем-то вроде. Но вы можете управлять его наличием с помощью других свойств, таких как zoom:1
.
Технически, наличие hasLayout у элемента означает что он отвечает за своё собственное отображение и отображение дочерних элементов. (В комбинации с min-height и width, вы можете получить что-то похожее на display:block). Это похоже на волшебную пыль, которой вы можете посыпать глюки отображения и они изчезнут.
Когда мы добавим zoom:1 и *display:inline
(хак со звёздочкой для IE6 и 7) в <li>, мы заставим IE 7 показывать их, как если бы они были inline-block:
<style> li { width: 200px; min-height: 250px; border: 1px solid #000; display: -moz-inline-stack; display: inline-block; vertical-align: top; margin: 5px; zoom: 1; *display: inline; } </style>
Почти готово! Остался только IE 6:
Поскольку в данном примере мы хотели использовать min-height, которое не поддерживается IE 6, но благодаря его неверному отображению свойства height, мы можем использовать его. Установим значение _height
(IE6 хак с подчёркиванием) в 250px, это сделает высоту всех <li> как минимум 250px, и если их контент не влезет, они растянутся до нужной высоты. Все остальные браузеры проигнорируют _height
.
Итак, после всех усилий, вот финальные стили CSS и разметка HTML:
<style> li { width: 200px; min-height: 250px; border: 1px solid #000; display: -moz-inline-stack; display: inline-block; vertical-align: top; margin: 5px; zoom: 1; *display: inline; _height: 250px; } </style>
<li> <div> <h4>This is awesome</h4> <img src="http://farm4.static.flickr.com/3623/3279671785_d1f2e665b6_s.jpg" alt="lobster" width="75" height="75"/> </div> </li>
Комментарии:
selenit2 (selenit)
26.02.2010 03:50:44
Елена Лунная
01.03.2010 15:33:06
selenit2 (selenit)
02.03.2010 02:54:14
Елена Лунная
02.03.2010 12:42:02