вертикальное выравнивание блока css Как создать свой сайт > Вебмастеру > Создание своего сайта > Блог Андрея Морковина > Вертикальное выравнивание блока

Вертикальное выравнивание блока: CSS, HTML, Div

Я не могу думать, когда я сосредоточиваюсь.
Йоги Берра.
3 ноября 2009 года

    Сегодня, уважаемый читатель, мы с вами разберёмся с проблемой вертикального выравнивания в блоке «div».

 

 

    Скорее всего вы уже знаете о существовании замечательного свойства CSS «vertical-align». И сам Бог велел нам пользоваться для вертикального выравнивания именно этим свойством (не зря же оно носит такое, говорящее само за себя, название).

Постановка задачи: Необходимо выровнять содержимое блока переменной высоты по центру относительно вертикали.

    Теперь приступим к решению поставленной задачи.

    Итак, у нас есть блок, высота его может меняться:

<div>Содержимое блока</div>

    Первое, что приходит в голову — сделать следующий финт:

<div style="vertical-align: middle">Содержимое блока</div>

    Есть все основания предполагать, что фраза «Содержимое блока» выровняется по центру высоты div-контейнера.

    Но не тут-то было! Никакого ожидаемого выравнивания по центру таким образом мы не добьёмся. А почему? Казалось бы, всё указано правильно. Оказывается, вот в чём загвоздка: свойство «vertical-align» можно применять только для выравнивания содержимого ячеек таблиц или для выравнивания строчных элементов друг относительно друга.

    По поводу выравнивания внутри ячейки таблицы, я думаю, всё понятно. А вот другой случай (со строчными элементами) я поясню.

Вертикальное выравнивание строчных элементов

    Предположим, есть у вас строка текста, которая «разбита» строчными тегами <span> на части:

<span id="perviy">Вас</span> <span id="vtoroy">приветствует</span> <span id="tretiy">кусок</span> текста!

    Под «строчным тегом» понимается контейнер, появление которого не приводит к переносу содержимого на новую строку.

    Действие же блочного тега приводит к переносу содержимого контейнера на новую строку.

<div> — это блочный тег. Если мы заключим куски текста в блоки <div>, то каждый из них окажется на новой строке. Используя тег <span>, который, в отличие от <div>, является строчным, переноса контейнеров на новую строку не будет: все контейнеры <span> останутся в одной строке.

    Контейнер <span> удобно использовать при задании для части текста особого форматирования (выделение цветом, другим шрифтом и т. д.)

    Для контейнеров <span> применим следующие свойства CSS:

#perviy{
    vertical-align:sub;
}

#vtoroy{
    vertical-align:3px;
}

#tretiy{
    vertical-align:-3px;
}

    В результате, строка текста будет иметь вот такой вид:

Выравнивание строчных элементов

    Это и есть ничто иное, как выравнивание строчных элементов по вертикали. И свойство CSS «vertical-align» с этой задачей прекрасно справляется.

    Мы немного отвлеклись, теперь возвращаемся к нашей основной задаче.

Выравнивание по вертикали в div-контейнере

    Несмотря ни на что, для выравнивания внутри div-контейнера мы будем использовать свойство «vertical-align». Как я уже говорил, данное свойство можно использовать в случае выравнивания строчных элементов (этот случай мы подробно рассмотрели выше и для выравнивания в div-контейнере он нам не подходит). Остаётся лишь использовать тот факт, что «vertical-align» работает для ячеек таблицы.

    Как же мы сможем это использовать? У нас же нет таблицы: мы работаем с div-контейнером.

    Ха, оказывается, очень просто.

    Свойство CSS «display» позволяет превратить наш блок div в ячейку таблицы. Сделать это можно легко и непринуждённо.

    Пусть у нас есть div класса «textalign»:

<div class="textalign">Содержимое блока</div>

    Для данного блока указываем следующее CSS-свойство:

.textalign{
    display: table-cell;
}

    Эта CSS-инструкция, чудесным образом, превратит наш блок div в ячейку таблицы, визуально никак его не изменив. А для ячейки таблицы мы сможем применять свойство «vertical-align» в полной мере и будет работать желаемая центровка по вертикали.

    Однако всё так просто закончиться не может. У нас же есть замечательный браузер IE. Он не умеет работать со свойством «display: table-cell» (предлагаю вам ознакомиться с табличкой, иллюстрирующей работоспособность данного CSS-свойства в разных браузерах). Поэтому нам придётся идти на различные ухищрения.

    Существует множество способов добиться вертикального выравнивания в div-контейнере для всех браузеров:

  • Способ с применением дополнительного вспомогательного div-контейнера;
  • Способ с использованием expression-а. Связан он с хитрым вычислением высот блоков. Без знания JavaScript тут не обойтись;
  • Использование свойства line-height. Данный способ подходит только для вертикального выравнивания в блоке известной высоты, а значит, в общем случае не применим;
  • Использование абсолютного и относительного смещения содержимого в случае браузера IE. Мне этот способ кажется наиболее понятным и простым. Кроме того, он реализуем для div-контейнера переменной высоты. На нём мы остановимся подробнее.

    Как вы понимаете, нам остаётся решить проблему вертикального выравнивания в IE, связанную с его непониманием свойства «display: table-cell» (ни IE6, ни IE7, ни IE8 с этим свойством не знакомы). Поэтому, воспользовавшись условным комментарием, специально для браузеров семейства IE мы укажем другие свойства CSS.

Условный комментарий

    Конструкция вида:

<!--[if IE]>
...
Инструкции, действующие только в случае выполнения условия в квадратных скобках
...
<![endif]-->

называется условным комментарием (будьте внимательны: вид условного комментария должен полностью соответствовать приведённому примеру, с точностью до пробела).

    Инструкции, содержащиеся в подобном условном комментарии, будут выполнены только в случае, если браузер, интерпретирующий данный код, принадлежит к семейству IE.

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

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

    Запомнили, пошли дальше.

Решение задачи

    Из-за всей этой петрушки нам нужно будет снабдить наш HTML-код двумя дополнительными контейнерами. Вот каким образом будет выглядеть наш блок с текстом:

<div class="textalign">
	<div>
		<span>Это какой-то проверочный текст. <br />Он состоит из двух строк.</span>
	</div>
</div>

    Для div-контейнера класса «textalign» задаются CSS-свойства, которые выравнивают его содержимое по вертикали для всех нормальных браузеров (кроме IE, разумеется):

display: table-cell;
vertical-align: middle;

    И ещё два свойства, которые задают ширину и высоту для блока:

width:500px;
height: 500px;

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

    Теперь начинаем дописывать свойства, связанные с выравниванием для браузеров семейства IE (именно для них мы использовали дополнительные блоки «div» и «span»).

    Обращаемся к тегу «div» внутри блока класса «textalign». Для этого, нужно сначала указать название класса, а потом, через пробел, тег, к которому мы обращаемся.

.textalign div{
    position: absolute;
    top: 50%;
}

    Такая конструкция означает: для всех тегов «div» внутри блока с классом «textalign» применить перечисленные свойства.

    Если всё оставить так, как есть, то div-контейнер, который находится внутри блока «textalign», будет позиционироваться относительно верхнего левого угла браузера. Нам же нужно, чтобы смещение на 50% по вертикали произошло относительно родительского блока. Для этого достаточно применить CSS-свойство «position: relative» к блоку «textalign». Об этих особенностях я подробно рассказываю в видеоуроке по работе с блоками «div».

    Соответственно, стили, заданные для блока «textalign», видоизменяются:

.textalign{
    display: table-cell;
    vertical-align: middle;
    width:500px;
    height: 500px;
    position: relative;
}

    Теперь левая верхняя точка текстового блока смещена вниз на 50%.

    Для пояснения происходящего я нарисовал иллюстрацию:

Вертикальное выравнивание, иллюстрация

    Как видно из картинки, определённого прогресса мы добились. Но это ещё не всё! Верхняя левая точка жёлтого блока действительно сместилась на 50% вниз относительно родительского (фиолетового) блока. Но нам-то нужно, чтобы на пятидесяти процентах высоты фиолетового блока находился центр жёлтого блока, а не его верхняя левая точка.

    Теперь в ход пойдёт тег «span» и его относительное позиционирование:

.textalign span{
    position: relative;
    top: -50%;
}

    Тем самым, мы сместили жёлтый блок вверх на 50% его высоты относительно начального положения. Как вы понимаете, высота жёлтого блока равна высоте центрируемого контента. И последняя операция со span-контейнером расположила наш контент посередине фиолетового блока. Ура!

Немного «подшаманим»

    Перво-наперво нам нужно спрятать «петрушку» от всех нормальных браузеров и открыть её для IE. Сделать это можно, конечно же, при помощи условного комментария, не зря мы с ним знакомились:

<!--[if IE]>

   <style type="text/css">
      .textalign div{
          position: absolute;
          top: 50%;
      }

      .textalign span{
        position: relative;
        top: -50%;
      }
    </style>

<![endif]-->

Есть небольшая проблемка. Если «центруемый» контент слишком высокий, то это приводит к неприятным последствиям: появляется лишняя высота вертикальной прокрутки.

Решение проблемы: нужно добавить свойство «overflow: hidden» блоку «textalign».

    Детально познакомиться со свойством «overflow» можно в видеоуроке по работе с блоками «div».

    Окончательный вид CSS-инструкций для блока «textalign» имеет вид:

.textalign{
    display: table-cell;
    vertical-align: middle;
    width:500px;
    height: 500px;
    position: relative;
    overflow: hidden;
    border: 1px solid black;
}

    При желании, вы можете посмотреть пример на HTML и CSS всего вышесказанного.

    Прошу пардону, забыл упомянуть один важный момент. Если вы будете пытаться задавать высоту блока класса «textalign» в процентном соотношении, то у вас ничего не выйдет.

Центровка в блоке переменной высоты

    Очень часто встречается необходимость задать высоту блока класса «textalign» не в пикселях, а в процентах от высоты родительского блока, и выровнять содержимое div-контейнера посередине.

    Загвоздка в том, что для ячейки таблицы невозможно этого сделать (а ведь блок класса «textalign» превращается именно в ячейку таблицы, благодаря свойству «display:table-cell»).

    В этом случае необходимо использовать внешний блок, для которого указано CSS-свойство «display:table» и уже для него задавать процентное значение высоты. Тогда вложенный в него блок с CSS-директивой «display:table-cell» благополучно унаследует высоту родительского блока.

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

    Классу «textalign» мы изменим значение свойства «display» с «table-cell» на «table» и уберём директиву выравнивания «vertical-align: middle». Теперь мы смело можем изменить значение высоты с 500 пикселей на, например, 100%.

    Таким образом, CSS-свойства для блока класса «textalign» будут иметь следующий вид:

.textalign{
    display: table;
    width:500px;
    height: 100%;
    position: relative;
    overflow: hidden;
    border: 1px solid black;
}

    Остаётся реализовать центрирование содержимого. Для этого div-контейнеру, вложенному в блок класса «textalign» (это тот самый жёлтый блок на рисунке), необходимо задать CSS-свойство «display:table-cell». Тогда он унаследует высоту в 100% от родительского блока «textalign» (фиолетовый блок). И нам ничто не помешает выровнять содержимое вложенного div-контейнера по центру свойством «vertical-align: middle».

    Получаем ещё один дополнительный список CSS-свойств для блока «div», вложенного в контейнер «textalign».

.textalign div{
    display: table-cell;
    vertical-align: middle;
}

    Вот и вся хитрость. При желании, вы можете посмотреть на свёрстанный блок переменной высоты с отцентрованным содержимым.

    Автор: Андрей Морковин.

 

Ещё материалы по этой теме:

 

 

Комментарии:

max
А как быть с блоками не фиксированной высоты?

Андрей Морковин
Центровка не привязывается к высоте блока. Приведенному варианту все равно, какая там высота.

Андрей Морковин
Кажется я понял, в чем была проблема. Дописал часть под названием «Центровка в блоке переменной высоты». Спасибо за комментарий, упустил этот факт из виду.

max
) да я как бы об этом.
Теперь надо проверить, но я думаю будет работать, когда например в боксе слева имаджа (допустим 500х500) а справа от нее текст выравнивается по вертикали.

L0CUST
с доктайпом xhtml не катит. не хочет он высоту в процентах

Dimox
Мне нравится этот способ. Надо как-то его запомнить =) Такие штуки мне еще, по-моему, не приходилось делать.

Андрей Морковин
Да, способ простой и понятный, этим он мне нравится больше все остальных извращений.

sman696
раньше не получалось выровнять в ie по вертикали, теперь знаю))
спасибо за способ

Андрей Морковин
Рад, что материал полезен.

mmm
Классно! Спасибо.

Андрей Морковин
Я старался

takobus
ие8 понимает display:table-cell (https://developer.mozilla.org/ru/docs/Web/CSS/display), поэтому ему заглушка не нужна. кроме того, можно унести ненужные стили .textalign{position: relative; overflow: hidden;} в conditional comments, т.к. они нужны только ие6-7

Андрей Морковин
Я проверял на ***, отключив заглушку для IE8 (использовал меньше либо равно IE7). Центровка не произошла. Вы проверяли? У меня нет установленного IE8, поэтому по человечески проверить не могу, доверяю browsershots.
Совершенно согласен, .textalign{position: relative; overflow: hidden;} самое место в conditional comments. Спасибо.

takobus
Да, проверила на чистой восьмерке при условии [if lt IE 8] display:table-cell работает. В compatibility view отрабатывается как у 7. А на *** действительно не работает в 8…
Кроме того, не совсем понимаю, зачем указывать у .textalign {display:table} для переменной высоты. Согласно Anonymous table objects это необязательно и без этого работает: «ячейки» растягиваются в зависимости от содержимого, height лишь задает минимальную высоту. Хотя, если уж «лишний» элемент из-за ие6-7 есть, то пусть будет и table Еще для border-collapse:collapse может пригодиться

Андрей Морковин
По поводу .textalign {display:table}:
Сделано это для того, чтобы можно было растянуть ячейку без всякой зависимости от высоты содержимого.

takobus
Поправка: на *** тоже нормально в 8, не туда посмотрела

Андрей Морковин
Я так и не понял, понимает IE8 display:table-cell или нет?

takobus
да, понимает

Андрей Морковин
Еще раз перепроверил скрин с сайта browsershots. ИЕ8 не понял директивы display:table-cell, поэтому применяю условный комментарий для всех браузеров семейства ИЕ.
Ваше мнение базируется на прочитанном или проверяли самостоятельно? Если проверяли, то как?

Never Lex
Огромное спасибо за статью! Страницу в избранное, РССку в ридер!

Андрей Морковин
Вот это правильный подход

Never Lex
Блин. А вот с комментами надо чёто делать. Выглядят ужасно, имхо. Все эти деревья вносят полнейший хаос в комментарии.

Андрей Морковин
А что с ними делать? Можно просто отключить деревья вообще, но так не возможно будет проследить ветвь обсуждения.
Я, лично, за отслеживание ветви обсуждения вопреки хаосу.

Never Lex
Лучше имхо писать перед комментом Имя того, к кому обращаешься. Хотя… можно подумать и сделать как-то альтернативно. Чтобы удобно было и ветвь прослеживалась легко.

Cандер
Классно! Попал случайно, через grabr, но радостно подписываюсь, ибо люблю подобные фокусы. Сам недавно с версткой возился, что и описал в ***

gaserge
где трюки то там?)))
помойму ты в ксс научился тока работать.
за статью респект.

Андрей Морковин
Мы с takobus все же выяснили поддерживает или нет IE8 свойство display:table-cell.
takobus пишет:
Теперь понятно, display:table-cell и прочие табличные значения display в ie8 не работают:
— в quirks mode;
— с доктайпом HTML 4.01 Transitional.
Работают с доктайпами:
— HTML 4.01 Strict;
— XHTML 1.0, 1.1;
— HTML5
Вы тестировали с HTML 4.01 Transitional, а я с XHTML 1.0 Transitional, использую по умолчанию.

Андрей Морковин
Спасибо, takobus! Теперь я буду в курсе (и не только я, а и все остальные, кто читает комментарии к статьям).

Never Lex
Теперь будем использовать только HTML 4.01 Strict

Tanё4ek
Огромное спасибо за пункт «Центровка в блоке переменной высоты»!!! то что нужно!!!
сначала не могла понять почему же у меня не получается, но потом поняла, что все из-за класса .textalign div. ко всем остальным divам в этом слое тоже применяются все свойства (я выровнила так весь сайт ***). Поэтому чтобы другие пользователи вашего блога не тупили как я))), прошу дать этому слою название:
Это какой-то проверочный текст. Он состоит из двух строк.
еще раз БОЛЬШОЕ СПАСИБО!!!!)))

Sarmat
Здравствуйте Андрей!
Как выяснилось, приведённый в иллюстрации метод работает не для всех доктайпов…
Предлагаю убрать «лишние» стили и всю css сократить до вот такой:
.textalign{
width:500px;
height: 500px; /*можно и в %%*/
position: relative;
overflow: hidden;
border: 1px solid black;
}
.textalign div{
position: absolute;
top: 50%;
}
.textalign span{
position: relative;
top: -50%;
}
Т.е. для всех браузеров будем использовать тот метод, который применяем для нужного нам выравнивания в IE6. Этих стилей достаточно, они поддерживаются всеми браузерами и удовлетворяют всем доктайпам. Да и условными комментами пользоваться не прийдётся.
По крайней мере, в моём случае, с приведённой разметкой сработало отлично — прошло все проверки.
Есть мнения?

Sarmat
Прошу прощения, если высота родителя задана в %%, то приведённые в предыдущем моём комменте стили не срабатывают для XHTML.

nikonian
Спасибо! Красиво и логично, проще для понимания чем воркэраунды на Хабре.

ulti-trade
нифига не помогло(
дисплей тебл-целл сделал, позишн слоя — абсолют… так и болтается прижатый текс к топовому краю, задаётся тегом к меня, но это наверное ничего не меняет??

Радиолюбитель
Тоже парился, вроде все по инструкции, а не опускается текст. Всему виной оказался float: left блока к которому я применял вертикальное выравнивание. Пришлось добавить еще один блок и все заработало.

ulti-trade
полный код с фиксом плз в студию!
для меня вопрос еще открыт

Радиолюбитель
блин, коммент обрезался, дайте контакты я скину

Борис
Поясните, куда надо вставить условный комментарий?

Sergey Orlov
Если у .textalign div не задать высоту то позиционирование в процентах top: -50%; работать не будет. а значит гудбай авто центрирование в ИЕ. можно лишь приблизительно попытаться его сделать.

Дмитрий
Что я не пробовал — ничего не работает. Что здесь можно сделать?
не фиксированной высоты, содержимое зависит
от описания товара. Надо выровнять по bottom.

 

⇓ 

Поделись ссылкой на Seoded.ru с друзьями, знакомыми и собеседниками в соцсетях и на форумах! А сам сайт добавь в закладки! Так победим.

Поделиться ссылкой на эту страницу в:

 

Полезные ссылки:

Как сделать кавычки на клавиатуре? Иконка сайта в HTML

 


основан в 2008 г. © Все права на материалы сайта Seoded.ru принадлежат Алексею Вострову.
Копирование (полное или частичное) любых материалов сайта возможно только с разрешения автора и при указании ссылки на источник.
Ослушавшихся находит и забирает Бабайка!