Каскадные Таблицы Стилей

индекс
324,89

Способ вертикального выравнивания блока с помощью настоящего vertical-align

Сегодня, верстая один макет, я, кажется, изобрел очередной небезынтересный способ вертикального выравнивания блока относительно родительского. Он не основан на превращении блоков в ячейки таблицы и не использует css-свойство position.

Требования

— Должна быть известна начальная высота родительского блока;
— Дочерний блок может иметь произвольный размер как по высоте, так и по ширине.

Возможности

— Работает в 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">
Но в данном случае это было бестолку и я все равно имел то, что изображено на картинке слева:
image
Почесав репу я за каким-то решил проверить, что будет, если после 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">&nbsp;</span>
</div>

* This source code was highlighted with Source Code Highlighter.

Оставить .iefix чисто инлайновым элементом тоже не получилось, ибо width и overflow применимо только к блочным элементам. Этот же вариант заработал в ие6 без изменений.
Теперь уже пример работал во всех браузерах, которые меня интересуют при верстке кроме FF2. Стоит отметить только один глюк в ИЕ6. Когда размер элемента с текстом уменьшается до размера самого большого слова (или другого элемента, которого невозможно разбить на несколько строк), ИЕ6 все-таки переносить элемент нулевой ширины .iefix на другую строчку, отчего высота всего блока увеличивается на 200 пикселей (величина line-height):
image

Трансформация номер три


Ну и на закуску остался 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">&nbsp;</span>
</div>

* This source code was highlighted with Source Code Highlighter.

Стоит отметить, что FF2 не захотел переносить текст, поэтому пришлось явно задать блоку с текстом width: 100%; в принципе это не так страшно, скорее всего реальная страница будет подразумевать конкретные значения для ширины текста.

В результате получился отличный способ вертикального выравнивания во всех популярных браузерах.
+68
1 октября 2009, 22:54
262

комментарии (59)

НЛО прилетело и опубликовало эту надпись здесь
+2
aratak #
Правильно ли я понял, что весь бенифис метода — использование line-height и inline-block?
0
homm #
В правильных браузерах да.
НЛО прилетело и опубликовало эту надпись здесь
0
homm #
Такой вариант тоже работает без проблем, просто я больше привык к описанному выше, меньше кода в css. Кто с вопросом знаком, сам выберет себе по душе.
НЛО прилетело и опубликовало эту надпись здесь
0
homm #
Заменил тег.
НЛО прилетело и опубликовало эту надпись здесь
+5
homm #
Вы можете пользоваться любым другим семантичным кросбраузерным способом вертикального выравнивания. На сколько мне известно, их ровно ноль.
НЛО прилетело и опубликовало эту надпись здесь
+1
kocten #
Извините, но у Вас не совсем правильное понимание слова Семантика — система правил определения поведения отдельных языковых конструкций. Семантика определяет смысловое значение предложений алгоритмического языка.
В верстке использование оберточных блоков следует избегать по возможности, но это не обязательное правило: если Вы дадите оберточному блоку класс из которого будет понятно что этот блок делает, что именно он оборачивает — семантика практически не пострадает.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
0
ferrari #
и не говори, его «пока заметная доля» каких-то жалких 25%. Сдается мне, счастье быстро не наступит.
0
kocten #
Так а я о чем все время говорю… я вообще оптимист по жизни, но нужно же быть хоть сколько-то реалистами: IE6 жив пока жива на Земле глупость, а это очень и очень долго и если честно я вижу в этом и положительные стороны: именно этот дибильный IE6 многих из нас заставляет совершенствовать свои знания быстрее чем мы это можем делать :)
0
GoldenHind #
забавно…
года не прошло с момента этого комментария, а ситуация уже изменилась в корне.
0
GoldenHind #
ну я html-nazi, но позволите ли мне воздержаться от криков о якобы кривости приведённого автором варианта, и просто избежать подобных конструкций в собственном коде?
А автору всё равно респект ибо способ работает хорошо, стабильно, да и наблюдения насчёт поведения ИЕ интересны.
+5
vithar #
0
homm #
Способ хоть и похожий, но на другом принципе.
0
Juniorro #
А что если высота контейнера неизвестна (определяется другим контентом)? Есть ли способ?
+2
GruZZ #
Есть. Через display:table-cell; для нормальных браузеров и небольной expression для IE. Всё это есть в комментарии выше. (Ладно, не удержусь и дам ссылку: cssing.org.ua/2007/04/26/another-css-valign-method/)
+7
andrew_tch #
Стало грустно после «Должна быть известна начальная высота родительского блока;»
А так неплохо. О line-height мало кто помнит. Кстати, для IE inline-block элементы проще верстать span'ами, и к черту семантику.
0
kocten #
ну здесь помоему фигня больше не в семантике, а в непредсказуемости поведения вложенных блоков, нужно будет потестить на приближенных к реальности примерах: вот у меня есть версия что проблемы начнуться, когда мы внутрь .block поместим дивы с float: left; и float: right;
Если пройдет испытание временем — то такой метод мне кажется неплохим и span'ы его сильно не испортят
–1
oknechirik #
тогда уж лучше ins — в него можно оборачивать блочные элементы, и сам он строчный при этом. и с бааальшой натяжкой можно будет сказать, что семантика соблюдена) — элемент по названию предназначен для вставки чего-либо (INSert), ну так мы и добавляем
–1
andrew_tch #
А давайте навалим дивов, только чтобы была семантика.
Был у меня один заказчик, просил таблицы на 6 столбцов верстать дивами, потому что таблицы — это не семантично вообще. Убедил-таки.
НЛО прилетело и опубликовало эту надпись здесь
0
N1k1t0ZzZ #
Супер, спасибо!
Буквально на днях столкнулся с такой проблемой, а вот уже и решение =)
–5
PiSaiK #
Баян
0
BassEast #
Кстати говоря, «Баян» уже давно сам стал баяном.
0
BassEast #
объяснит кто-нибудь, за что минус?
слово «Баян» уже реально надоело, все кому не лень им отписываются, похоже ради того, дабы отписаться, лучше тогда молчать и мысленно не соглашаться с мнениями.
0
PiSaiK #
Да. ты прав. лучше молчать. Но то что написали, очень древняя вещь для тех, кто умеет верстать
0
GmasteR #
Подскажите что-то поновее?!
0
PiSaiK #
Более нового ничего нет. Это решение весьма оптимальное, и по крайней мере работает везде. У меня просто нет времени, чтобы заниматься рукоприкладством и искать новые неизведанные способы. Ничего нет проще того, что уже работает
–5
Triall #
По-мойму все давно знают о таком способе.
0
kocten #
не все, я не знал… почему-то каждый наталкиваясь на знакомый метод считает нужным прокомментировать это… при том что давно всем известно, что действительно новые изобретения случаются крайне редко, тем более в нашей стране, все равно все так или иначе заимствованно из-за бугра, а вот то что многие статьи почти полностью копипастятся внутри самого хабра по 5 раз мало кто замечает…
+2
jahson #
Я совсем недавно изучал вопрос и вот одна из возможных ссылок: haslayout.net/css-tuts/Vertical-Centering
Изобретения не вышло.
0
tenshi #
white-space: nowrap
НЛО прилетело и опубликовало эту надпись здесь
0
oknechirik #
еще один источник www.cssplay.co.uk/ie/valign.html
0
homm #
Источник чего? Ни в одном браузере не заработало.
+5
Dimox #
Красивое решение. Жаль только, что с DOCTYPE Transitional не работает.
НЛО прилетело и опубликовало эту надпись здесь
0
Dimox #
Попробуйте вместо HTML 4.01 Strict, который используется в примерах, задействовать HTML 4.01 Transitional или XHTML 1.0 Transitional.

P.S. Зато в HTML5 работает.
НЛО прилетело и опубликовало эту надпись здесь
0
Dimox #
Точно, я забыл уточнить, что смотрел в Opera 10.
+4
BassEast #
ссылки на Стью Никольса и прочих, можно хоть целый день кидать, а тут вот, Наш человек решил задачу по-новому, ну, разве это не здорово? =)
–3
egorinsk #
Все бы хорошо, если бы не практически полная бесполезность примера: ну где вы найдете блоки с фиксированной высотой, да еще и в пикселях?? (хотя line-height можно и в em задать конечно)
+4
homm #
ну где вы найдете блоки с фиксированной высотой, да еще и в пикселях??
В данном случае, как раз способ был найден для конкретного применения, а не наоборот:
image
+1
Dimox #
На практике это встречается. Не надо говорить о бесполезности.
0
deerua #
Думаю как клёво что придумали.
Смотрю в код, а там марин-топ 100пх, лайн-хейгт 200пх и в transitional не работет ;)
0
homm #
Не понял, что не так с марин-топ 100пх?
0
deerua #
Затупил, сорри.
Но что делать с Transitional не ясно ;)
–1
gadostnik #
это, конечно, валидно и лаконично, но старая занудная таблица потребует меньше итогового кода…
–3
squint #
Замечательно! Осталось научиться писать ногой и ходить на руках.
0
MrGD #
Остроумное решение, но как по мне: слишком много «хаков» и усложнений, использовать врятли буду.
0
torbasow #
Попробовал сейчас этот способ, другие по разным причинам не нравились. Вроде всё работает как надо, с двумя оговорками: во-первых, контейнеру пришлось указать не только line-height, но и такой же height оставить, иначе он схлопывается по высоте содержимого; во-вторых, в старых IE всё заработало с p-блоками и общими стилями, без специальных выкрутасов.

Причина в обоих случаях, подозреваю, одна и та же: у меня вложенные (центрируемые по вертикали) p-блоки зафлоачены.
0
torbasow #
Пардон, ошибся. Дезавуирую предыдущий комментарий.
0
almazmusic #
Если писать разметку без пробелов в одну строку, то не работает в ИЕ7. Час ушёл на это.
0
almazmusic #
Ошибочка. Оказывается если внутри текст есть комментарий, то способ отказывается работать :( Ещё 20 минут.

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