Кроссбраузерный inline-block

http://blog.mozilla.com/webdev/2009/02/20/cross-browser-inline-block/
  • Перевод
Разрешите представить вам перевод статьи «Cross-Browser Inline-Block», написанной Райном Доэрти холодным февралем 2009 года. В статье рассказывается о верстке элементов списка с установкой для свойства display значения inline-block. Статья об этом, а также о трудностях, возникающих в процессе достижения результата и о методах их «лечения».



Inline-block, заманчивое значение для свойства display, которое обещает очень много, а выполняет совсем мало. Очень часто я получал PSD-файлы, подобные этому:


и плакал.

Обычно такой способ отображения не вызывает проблем. Фиксированная ширина, фиксированная высота, float: left и готово. Если бы не одно, но! Дизайн должен отображаться корректно при любом количестве содержимого. В нашем случае, если в одном из блоков окажется чуть больше данных, то он «сломает» всю сетку.



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

Начнем с простого примера, где у пунктов списка для свойства display установлено значение inline-block:

<ul>
    <li>
        <h4>This is awesome</h4>
        <img src="1450821541436477177797"
        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 и в Opera:



Кажется, будто что-то не так с вертикальным выравниванием. Говоря по правде, никаких ошибок нет, это как раз корректное поведение браузера, но совсем не тот результат, которого мы бы хотели.

А происходит здесь следующее, базовая линия (baseline) каждого элемента <li> выравнивается с базовой линией родительского элемента <ul>. Вы спросите, что такое базовая линия? Лучше один раз увидеть, чем сто раз услышать:



Базовая линия на рисунке выше обозначена линией, идущей через основание символов. Значением по-умолчанию для свойства vertical-align у inline и inline-block элементов является baseline. Это значит, что базовая линия элементов выравнивается с базовой линией родителя. На рисунке ниже представлен пример такого выравнивания:



Как видите, каждая базовая линия блоков на рисунке выше выравнена по базовой линии текста «This is the baseline», который не является элементом <li>. Это просто текстовый узел, находящийся непосредственно в <ul>, помещенный туда в качестве индикатора расположения базовой линии элемента <ul>.

Получить желаемый изначально вариант выравнивания довольно просто, достаточно для свойства vertical-align указать значение top и получить в результате отличную сетку:



Вот только это не работает в Firefox 2, IE 6 и 7:



Для начала займемся Firefox 2.

Firefox 2 не поддерживает значение inline-block, зато отлично понимает специфичное для Мозиллы значение -moz-inline-stack для свойства display. Оно приводит к результатам, подобным действию inline-block. Когда мы добавляем его перед display: inline-block, то Firefox 2 игнорирует вышеуказанное, так как не понимает его, и использует -moz-inline-stack. Другие браузеры используют inline-block, игнорируя непонятное для них -moz-inline-stack.

<style>
    li {
        width: 200px;
        min-height: 250px;
        border: 1px solid #000;
        display: -moz-inline-stack;
        display: inline-block;
        vertical-align: top;
        margin: 5px;
    }
</style>


К сожалению, это вызывает небольшой баг:



Честно, я не знаю, что является его причиной. К счастью, лечится он довольно просто обертыванием всего содержимого элемента <li> дополнительным <div>.

<li>
        <div>
            <h4>This is awesome</h4>
            <img src="1450821541436477177797"
            alt="lobster" width="75" height="75"/>
        </div>
</li>




Теперь перейдем к IE 7. Он тоже не поддерживает inline-block, но мы можем использовать трюк, благодаря которому элементы <li> будут выводиться на экран так, будто используют значение inline-block. Как? Будем использовать hasLayout, волшебное свойство IE, делающее доступными многие манипуляции. Вы не можете явно указать для элемента hasLayout: true или сделать это каким-либо подобным простым образом, однако можете запустить механизм, указав zoom: 1.

Технически элементы с hasLayout, установленным в значение true сами отвечают за рендеринг самих себя и дочерних элементов. Объедините это с min-height и width, и получите результат, очень близкий к display: block. Это как магический порошок, заставляющий исчезать все появляющиеся при отображении проблемы.

Когда мы добавим zoom: 1 и *display: inline (звездочка является хаком для IE 6 и IE 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:



IE 6 не поддерживает min-height, но взамен мы можем использовать его неверное обращение к свойству height. Установим для _height (обратите внимание на подчеркивание спереди) значение в 250px и получим все элементы <li> с нужной высотой. Если же содержимое превысит указанную величину, то просто растянет свой контейнер. Все остальные браузеры проигнорируют _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="1450821541436477177797"
            alt="lobster" width="75" height="75"/>
        </div>
</li>
Метки:
Поделиться публикацией
Похожие публикации
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 65
    • +9
      Неясно почему минусуют. Ведь была уже статья, кто-то переводил раньше уже. Зачем делать одну работу несколько раз?
      • +5
        chikuyonok.ru/2011/04/inline-vertical-align/ статья от всеми нами любимого автора Сергея Чикуёнка — подход очень похожий
      • +4
        На самом деле, для укрощения старых IE достаточно использовать тэги, которые по умолчанию ведут себя как inline-block: например, ins и del.
        <ins style="display: inline-block;width: 25%; ">
        <div style="float: left; width: 100%;">
        это инлайн-блок
        </div>
        </ins>
        

        Вот пример использование, когда товары в магазине автоматически выстраиваются в подходящее число колонок по ширине в зависимости от ширины окна браузера (надеюсь не рухнет). Сам метод описывал еще лет 5 назад один из сотрудников студии Лебедева (по крайней мере я узнал от них).

        Может это и не самое кошерное решение с точки зрения семантики, зато оно простое и главное работающее без хаков под каждую версию браузера.
        • 0
          Единственное, у вас в конце, где 3 букета, они выравниваются по середине.
          • 0
            Это настройки общего дива, в котором все инсы.
          • +6
            «для укрощения старых IE достаточно использовать» любый inline элементы + hasLayout
            • 0
              Крайне некошерное, данные должны быть отдельно, а оформление отдельно.
              Все рецепты, содержащие дополнительное обёртывание или замену тега, противоестественны.
              • +1
                Да, в идеальном мире для идеального браузера. Я еще не видел настоящей кошерной верстки, рассчитаной на весь сегмент браузеров от хотя бы ie7 и выше — везде так или иначе приходится добовлять хотя бы один лишний элемент.
                • 0
                  Значит её нет, раз вы её не видели.
                • НЛО прилетело и опубликовало эту надпись здесь
                  • –2
                    Только если ему не следовать.
              • 0
                Полезная вещь.
                Я делал по другому: брал все в дивы и после 4го дива писал
                • +1

                  • 0
                    <br clear="all" />

                    получилось ;)
                    • –1
                      Наверное, все же clear=«both»?)
                      • 0
                        Нет, именно так, попробуйте.
                        • 0
                          Да-да, у вас как атрибут, а я имел в виду стиль.
                        • +1
                          тьфу блин,
                          <br style="clear:both">
                          • –1
                            А зачем делать это стилем если есть атрибут? Да и способ не лучший.
                        • +3
                          Смысл как раз в том, чтобы число элементов попадало в одну строку автоматически. Даже таблицей так не сверстать…
                          • 0
                            Это же программированием решается, и уже не важно что там в верстке)
                            • 0
                              В зависимости от ширны окна уместить либо три либо пять либо семь блоков?
                              • 0
                                о, нет, конечно (речь о таблицах)
                                • 0
                                  Чем вам поиск по яндекс.картинкам не пример?
                        • +4
                          zoom: 1;
                          display:-moz-inline-box;
                          -moz-box-orient:vertical;
                          display:inline-block;
                          _display:inline;
                          *display:inline;
                          vertical-align: top;

                          По-моему работает без всяких обверток в лишние div, в том числе в FF2.
                          • +8
                            Я уже забыл, когда видел последнего посетителя с ФФ2
                            • +4
                              Ну это для понта.
                              • 0
                                Прочитав Ваш комментарий, решил посмотреть как обстоят дела на моём сайте ит-шной наклонности.
                                Знаете, у меня есть заходы не то что с Fx2, но даже с Fx1.5, хотя они все в пределах статистической погрешности:
                                img
                              • +2
                                не тру. Сначала идет _хак для ИЕ6, затем общий зак для 6 и 7 — *.
                                В данном случае этот _хак не нужен, звездочка все равно к обоим применится.
                                • –1
                                  Звездочка, насколько я помню из детства, только с IE7 работает. Согласен, что можно заменить на комментарий "//", чтобы оставить одну декларацию.
                                  И перед zoom еще, чтобы Safari исключить.
                                  • +3
                                    Виноват. И вправду на IE6 срабатывает. Детство мое было неправильное.
                              • НЛО прилетело и опубликовало эту надпись здесь
                                • –2
                                  ничего не исчезает, не знаете сути проблемы не пишите чушь
                                  • –1
                                    Возьмитесь за правый край старого осла (гг) и подергайте сверстанный по статье сайт влево-вправо. Поймете, о чем речь.
                                • +9
                                  Чем дольше поддерживаешь IE6, тем дольше он проживет.
                                  • +5
                                    Ну на самом деле тихий консенсус в отрасли состоит в том, чтобы по-умолчанию поддерживать IE6 лишь частично. То есть верстка не должна разваливаться, а сам сайт должен оставаться рабочим, но попиксельной точности уже никто не требует.
                                  • +3
                                    Я в таких случаях просто использую таблицу. Несмотря на то, что идеалогически это куда более худшее решение, оно значительно быстрее рендерится в браузерах.
                                    • 0
                                      Несколько дней назад столкнулся с подобной проблемой — допилил функционал сортировки таблицы на мониторинге, в итоге заметил неправильное отображение в ИЕ7 (под ИЕ6 — не делали, согласно ТЗ) ссылок из серии Добавить в закладки/избранное/на сайт. display: inline-block в ИЕ7 не работал почему-то.
                                      Оказалось, если в <div>`е есть несколько <a> и <p>, то inline-block — не работал, а inline — не поддерживает border как надо. Выход — замена <p> на <span> — возможно, технологи скажут, что это семантически неверно, но работает.
                                      • 0
                                        Сохранять семантику при ие7 — тяжкое дело. А заказчик упёрто пытается указывать на «таблицы для нетабличных данных».
                                        • +1
                                          Ссылку на статью для этого перевода я нашел именно там )
                                        • +2
                                          CSS-хаки можно использовать более элегантно:

                                          li {
                                          min-height: 250px;
                                          height: auto !important; // IE6 в одном селекторе игнорирует important
                                          height: 250px;
                                          display: inline;
                                          display: inline-block; // IE такого не знает и воспользуется предыдущим свойством
                                          zoom: 1;
                                          }
                                          • +3
                                            два слеша не являются комментариями в css
                                            • +3
                                              Ну это же не css-файл :) Лень было просто.
                                            • НЛО прилетело и опубликовало эту надпись здесь
                                            • –2
                                              Превосходная статья, не встречал раньше подобного метода. Теперь буду использовать! Спасибо за перевод.
                                              • –5
                                                Хорошее решение. Но я бы использовал джаваскрипт, просто чтобы выровнять высоту всех блоков по самому высокому +3px
                                                И тоже самое при попытке изменить размер окна
                                                • +1
                                                  Легендарная прямо таки статья
                                                  • 0
                                                    FF2 уже вне игры, хаки для IE в эпоху Conditional Comments смотрятся как атавизм.
                                                    Что еще удивительно, нашлось немало тех, кто за два года с выхода статьи, ни разу на неё не наткнулся.
                                                    Или это хабр глючит выдавая архивные посты?
                                                    • –1
                                                      Нее, просто Чикуёнок мимоходом упомянул эту статью, вот все и кинулись читать.
                                                    • +1
                                                      Во-первых firefox 2 уже давно морально устарел и вот это можно выкинуть
                                                      display: -moz-inline-stack;
                                                      Во-вторых на резиновых сайтах возникали проблемы с таким кодом для firefox 2, так что там все чуть сложнее было, если кому надо могу поискать решение
                                                      В-третьих вы не решили проблему отступов у inline элементов, тоесть если убрать маргины то блоки будут не вплотную друг к другу стоять. Там нужно у контейнера несколько параметров обнулить, а у вложенного тега все восстановить.
                                                      Ну и код для ие6 — 7 лучше выносить в CC, но это и так все знают ))
                                                      • 0
                                                        Вот кстати сниппет, для того чтобы убрать отступы между inline-block блоками
                                                        snipplr.com/view/49933/display-inlineblock-/
                                                        может кому пригодится
                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                        • +1
                                                          Еще -moz-inline-stack; не работал в связке с position:relative;, а в Opera inline-block + relative переодически глючит до сих пор.
                                                          • –1
                                                            И тут на помощь приходит дремучий. Как ни странно, это было бы лучшим решением.
                                                            • –2
                                                              Пардон. Дремучий table
                                                              • 0
                                                                Вы не поняли, в чём проблема table. А проблема эта в том, что table не умеет переносить ячейки на новую строку или оставлять на предыдущей в зависимости от ширины окошка.
                                                                • 0
                                                                  Резиновая верстка…
                                                                  Я inline-block использую, когда нужно сделать горизонтальное ul-меню, чтобы оно размещалось в центре блока, т.е. реагировало на text-align: center;

                                                                  Пока другого подобного решения не встречал.
                                                              • +2
                                                                Да, хороший рецепт. 10 июня прошлого года я приводил гиперссылку на сборник, состоящий из этого и нескольких других преполезнейших рецептов (общим числом полсотни), так что очень рад, что у Вас дошли руки перевести один из них. Поглядите на них — быть может, и другие приглянутся для перевода или хотя бы употребления.
                                                                • +1
                                                                  Спасибо, обязательно посмотрю.
                                                                  • +1
                                                                    Вечера доброго!
                                                                    А можно еще раз ссылочку, а то этот адрес уже канул в неизвестность?
                                                                    • 0
                                                                      По-видимому, та блогозапись была уничтожена физически из-за какого-то глюка Хабрахабра или стёрта модераторами хаба CSS. Сейчас я не нахожу в своём блоге ни одной блогозаписи от 10 июня 2010 года.
                                                                  • 0
                                                                    Привет вам из позапрошлого года.

                                                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.