Сегодня, верстая один макет, я, кажется, изобрел очередной небезынтересный способ вертикального выравнивания блока относительно родительского. Он не основан на превращении блоков в ячейки таблицы и не использует css-свойство position.
— Должна быть известна начальная высота родительского блока;
— Дочерний блок может иметь произвольный размер как по высоте, так и по ширине.
— Работает в IE6+, O9+, FF2+, webkit;
— Тру vertical-align выравнивание со всеми допустимыми значениями;
— Одинаковое поведение во всех браузерах (незначительные отклонение при некоторых условиях в ие6 будут оговорены ниже);
— При вырастании дочернего блока выше «папочки», родительский блок расширяется;
— Ни грамма JavaScript.
Итак, для начала рассмотрим заготовку, которую я хочу использовать для рассказа.
Мы имеем блок .container фиксированной высоты 200px и находящийся внутри него блок с текстом, пусть для определенности нам нужно выровнять его по середине родительского контейнера. Также я добавил снизу обычный текст, который при малой ширине окна перекрывается текстом из контейнера. От этого неприятного эффекта мы тоже избавимся.
Know how моего метода заключается в том, что вместо того, чтобы указывать настоящую высоту блока .container, мы указываем line-height в те же 200px, а дочерний блок делаем встроенным блоком (display: inline-block;). Самая большая неприятность, которая поджидает во всем методе, заключается в том, что значение line-height наследуется на дочерний блок и для него его придется задать еще раз:
И мы получаем вот такую страничку, уже работающую в IE8, O9+, FF3+, webkit. Как я и обещал, при уменьшении окна до такого размера, когда дочерний элемент становиться выше родительского, родительский растягивается. Я нарочно заостряю на этом внимание, так как данное поведение может очень и очень пригодиться в реальных макетах, когда маленький заголовок лучше смотрится посреди строки, а большой должен раздвигать следующий далее контент.
Достигнув такого результат я конечно обрадовался, но естественно, я не верил в успех, пока не проверил в ие6 и 7 и, как оказалось, не зря. На самом деле не все так страшно, как кажется. Ответ на первый вопрос, который у меня возник, я знал заранее: старые ИЕ не могут применять значение display: inline-block к изначально блочным элементам. Сказано-сделано, <div class="block"> без сожаления был заменен на <span class="block">
Но в данном случае это было бестолку и я все равно имел то, что изображено на картинке слева:
Почесав репу я за каким-то решил проверить, что будет, если после inline-block элемента поставить настоящий инлайновый элемент, скажем текст. Как ни странно это возымело нужное действие и я получил то, что на картинке справа. Ну что-ж, запишем в копилку глюков ИЕ еще один: одиночный инлайн-блочный элемент принудительно становиться блочным. Осталось только упаковать новый инлайновый элемент так, чтобы он не мешал другим браузерам и не занимал места. Получилось как-то так:
Оставить .iefix чисто инлайновым элементом тоже не получилось, ибо width и overflow применимо только к блочным элементам. Этот же вариант заработал в ие6 без изменений.
Теперь уже пример работал во всех браузерах, которые меня интересуют при верстке кроме FF2. Стоит отметить только один глюк в ИЕ6. Когда размер элемента с текстом уменьшается до размера самого большого слова (или другого элемента, которого невозможно разбить на несколько строк), ИЕ6 все-таки переносить элемент нулевой ширины .iefix на другую строчку, отчего высота всего блока увеличивается на 200 пикселей (величина line-height):
Ну и на закуску остался FF2, который как известно, не понимает инлайн-блоков, но может это эмулировать через значение display: -moz-inline-stack;. Свойство -moz-inline-stack требует чтобы его содержимое было обернуто в еще один блок, поэтому HTML код здесь немного разрастается:
Стоит отметить, что FF2 не захотел переносить текст, поэтому пришлось явно задать блоку с текстом width: 100%; в принципе это не так страшно, скорее всего реальная страница будет подразумевать конкретные значения для ширины текста.
В результате получился отличный способ вертикального выравнивания во всех популярных браузерах.
Требования
— Должна быть известна начальная высота родительского блока;
— Дочерний блок может иметь произвольный размер как по высоте, так и по ширине.
Возможности
— Работает в IE6+, O9+, FF2+, webkit;
— Тру vertical-align выравнивание со всеми допустимыми значениями;
— Одинаковое поведение во всех браузерах (незначительные отклонение при некоторых условиях в ие6 будут оговорены ниже);
— При вырастании дочернего блока выше «папочки», родительский блок расширяется;
— Ни грамма JavaScript.
Итак, для начала рассмотрим заготовку, которую я хочу использовать для рассказа.
Мы имеем блок .container фиксированной высоты 200px и находящийся внутри него блок с текстом, пусть для определенности нам нужно выровнять его по середине родительского контейнера. Также я добавил снизу обычный текст, который при малой ширине окна перекрывается текстом из контейнера. От этого неприятного эффекта мы тоже избавимся.
Трансформация номер раз
Know how моего метода заключается в том, что вместо того, чтобы указывать настоящую высоту блока .container, мы указываем line-height в те же 200px, а дочерний блок делаем встроенным блоком (display: inline-block;). Самая большая неприятность, которая поджидает во всем методе, заключается в том, что значение line-height наследуется на дочерний блок и для него его придется задать еще раз:
.container {
line-height: 200px;
}
.block {
display: inline-block;
line-height: 1.2;
vertical-align: middle;
}
И мы получаем вот такую страничку, уже работающую в IE8, O9+, FF3+, webkit. Как я и обещал, при уменьшении окна до такого размера, когда дочерний элемент становиться выше родительского, родительский растягивается. Я нарочно заостряю на этом внимание, так как данное поведение может очень и очень пригодиться в реальных макетах, когда маленький заголовок лучше смотрится посреди строки, а большой должен раздвигать следующий далее контент.
Трансформация номер два
Достигнув такого результат я конечно обрадовался, но естественно, я не верил в успех, пока не проверил в ие6 и 7 и, как оказалось, не зря. На самом деле не все так страшно, как кажется. Ответ на первый вопрос, который у меня возник, я знал заранее: старые ИЕ не могут применять значение display: inline-block к изначально блочным элементам. Сказано-сделано, <div class="block"> без сожаления был заменен на <span class="block">
Но в данном случае это было бестолку и я все равно имел то, что изображено на картинке слева:
Почесав репу я за каким-то решил проверить, что будет, если после inline-block элемента поставить настоящий инлайновый элемент, скажем текст. Как ни странно это возымело нужное действие и я получил то, что на картинке справа. Ну что-ж, запишем в копилку глюков ИЕ еще один: одиночный инлайн-блочный элемент принудительно становиться блочным. Осталось только упаковать новый инлайновый элемент так, чтобы он не мешал другим браузерам и не занимал места. Получилось как-то так:
<style type="text/css">
.iefix {
display: none;
}
</style>
<!--[if lte IE 7]>
<style type="text/css">
.iefix {
display: inline-block;
width: 0;
overflow: hidden;
}
</style>
<![endif]-->
<div class="container">
<span class="block">
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s
</span>
<span class="iefix"> </span>
</div>
* This source code was highlighted with Source Code Highlighter.
Оставить .iefix чисто инлайновым элементом тоже не получилось, ибо width и overflow применимо только к блочным элементам. Этот же вариант заработал в ие6 без изменений.
Теперь уже пример работал во всех браузерах, которые меня интересуют при верстке кроме FF2. Стоит отметить только один глюк в ИЕ6. Когда размер элемента с текстом уменьшается до размера самого большого слова (или другого элемента, которого невозможно разбить на несколько строк), ИЕ6 все-таки переносить элемент нулевой ширины .iefix на другую строчку, отчего высота всего блока увеличивается на 200 пикселей (величина line-height):
Трансформация номер три
Ну и на закуску остался FF2, который как известно, не понимает инлайн-блоков, но может это эмулировать через значение display: -moz-inline-stack;. Свойство -moz-inline-stack требует чтобы его содержимое было обернуто в еще один блок, поэтому HTML код здесь немного разрастается:
<div class="container">
<span class="block">
<span>
Lorem Ipsum is simply dummy text of the printing and typesetting industry.
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s
</span>
</span>
<span class="iefix"> </span>
</div>
* This source code was highlighted with Source Code Highlighter.
Стоит отметить, что FF2 не захотел переносить текст, поэтому пришлось явно задать блоку с текстом width: 100%; в принципе это не так страшно, скорее всего реальная страница будет подразумевать конкретные значения для ширины текста.
В результате получился отличный способ вертикального выравнивания во всех популярных браузерах.