Разбираемся с vertical-align

Луис Лазарис  9 марта 2012

«Опять vertical-align не работает!» — вздохнёт веб-разработчик.

CSS-свойство vertical-align — одно из тех, которые с виду очень просты, но могут вызвать вопросы у начинающих разработчиков. Я думаю, что даже у многих ветеранов CSS когда-то были проблемы с тем, чтобы его до конца понять.

В этой статье я постараюсь в понятной форме рассказать про это свойство.

Чего оно не делает

Распространенное заблуждение о vertical-align состоит в том, что применяясь к одному элементу, оно заставляет все элементы внутри него изменить свою вертикальную позицию. Например, когда элементу задан vertical-align:top, это подразумевает, что его содержимое поднимется к его же верхней границе.

Вспоминаются времена, когда мы делали раскладки на основе таблиц:

<td valign="top">
    Что-нибудь…
</td>

В данном примере с ячейкой таблицы использование свойства valign (в настоящее время исключенного из HTML5) приведёт к тому, что элементы внутри ячейки прижмутся к её верху. И естественно, когда верстальщики начинают использовать vertical-align, они думают, что получится то же самое, и содержимое элемента выровняется в соответствии со значением свойства.

Но vertical-align работает не так.

Чем оно является на самом деле

Использование свойства vertical-align может быть разбито на три простых для понимания правила:

  1. Оно применяется только к строчным элементам inline или строчным блокам inline-block.
  2. Оно влияет на выравнивание самого элемента, а не его содержимого (кроме случаев, когда применяется к ячейкам таблицы).
  3. Когда оно применяется к ячейке таблицы, выравнивание влияет на содержимое ячейки, а не на неё саму.

Иными словами, следующий код не даст никакого эффекта:

div {
    vertical-align:middle; /* эта строка бесполезна */
    }

Почему? Потому что <div> — это не строчный элемент и даже не строчный блок. Конечно, если вы сделаете его строчным или строчным блоком, то применение vertical-align даст желаемый эффект.

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

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

Несколько картинок

Вот картинка с пояснительным текстом, которая поможет вам понять, что происходит при вертикальном выравнивании строчных элементов:

А вот пример, в котором есть несколько строчных элементов, один из которых прижат к верху.

Ключевые слова

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

  • baseline, значение по умолчанию или «изначальное»
  • bottom
  • middle
  • sub
  • super
  • text-bottom
  • text-top
  • top

Возможно, многие из них вы не будете использовать, но было бы неплохо знать все имеющиеся варианты. Например, на демо-странице, из-за того что значение vertical-align для <input> установлено как top, он выровнен по самому высокому элементу в строке (большой картинке).

Однако если вы не хотите выравнивать элемент относительно картинок или других строчных элементов, обладающих блочными свойствами, вы можете выбрать значение text-top или text-bottom, тогда элементы будут выравниваться относительно текста в строке.

О ключевом слове middle

К сожалению, правило vertical-align:middle не выровняет строчный элемент по середине самого высокого элемента в строке (как вы, возможно, ожидали). Вместо этого значение middle заставит элемент выровняться по середине высоты гипотетической строчной буквы «x» (так же называемой x-height). Потому, мне кажется, что это значение на самом деле должно называться text-middle, чтобы стало понятно, какой будет результат.

Взгляните на пример, где я увеличил размер шрифта так, чтобы размер x-height стал гораздо больше. После этого станет понятно, что значение middle не получится использовать очень часто.

Числовые значения

Возможно, вы не знали о том, что vertical-align принимает числовые и процентные значения. Однако это так, и вот примеры их использования:

input {
    vertical-align:100px;
    }
span {
    vertical-align:50%;
    }
img {
    vertical-align:-300px;
    }

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

Заключение

Если в одной фразе подводить итог о том, как использовать это традиционно неправильно понимаемое свойство, я бы сказал:

Свойство vertical-align работает только со строчными элементами или строчными блоками и ячейками таблицы. В случае применения не к ячейкам таблицы, оно действует на сам элемент, а не на его содержимое.

Перевод оригинальной статьи «Understanding CSS’s vertical-align Property» Луиса Лазариса (Louis Lazaris), опубликованной на сайте «Impressive Webs».

Перевод выполнил Андрей Мотошин.

Теги:

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

  1. Roman Petrenko 9 марта 2012 в 15:21

    Отлично изложено. Может быть вы выпускаете журнал на который можно подписатся. Если да то скиньте мне на имаил как можно подписаться. Еще раз спасибо!

  2. SilentImp 9 марта 2012 в 16:52

    Вы имеете в виду offline издание?
    Если online, то вы можете подписаться на новости и обновления в твиттере: https://twitter.com/#!/webstandards_ru/

  3. SilentImp 9 марта 2012 в 17:09

    Отличная статья, кстати.

  4. Михаил 10 марта 2012 в 2:54

    Роман, там вверху справа в браузере есть rss ;)

  5. Orcinus Orca 10 марта 2012 в 17:03

    Спасибо за разъяснения, я даже не знал, что он только к инлайнам применяется. По этому обходил трюки с его использованием.

  6. Денис 12 марта 2012 в 3:56

    vertical-align у родителя сработает если у детей vertical-align: inherit;

  7. SilentImp 12 марта 2012 в 19:04

    Денис, я не очень понял что вы имеете в виду. Вы не могли бы написать и выложить кейс?
    На том же http://jsfiddle.net/ ?

  8. Денис 12 марта 2012 в 20:11

    Пример: http://jsfiddle.net/jMQv2/

  9. Евгений 16 марта 2012 в 16:53

    Отличный перевод, только вот относительно ссылочек — не очень удобно на сайте без

    :visited
    
  10. Роберт 7 апреля 2012 в 22:46

    Не хватает информации об особенности поведения vertical-align в разных браузерах и о различных подводных камнях.

    Из интересных особенностей, что недавно встречал - inline-block с overflow:hidden выравнивается по разному, в разных браузерах http://jsfiddle.net/dw8EW/12/

  11. SelenIT 27 апреля 2012 в 21:30

    Роберт, это не баг, а специфицированная особенность — последняя фраза в разделе о сабже гласит:

    The baseline of an 'inline-block' is the baseline of its last line box in the normal flow, unless ... if its 'overflow' property has a computed value other than 'visible', in which case the baseline is the bottom margin edge.

    Баг как раз только в Хроме, который, к сожалению, вообще неважно справляется с инлайновым форматированием (у него и проценты для vertical-align работают не по стандарту, и не только).

  12. FeelGood 5 июня 2012 в 14:18

    Остается загадкой почему же разработчики css не догадались сделать замену vertical-align для блочных элементов. Это же очевидная необходимость.

  13. Вадим Макеев 5 июня 2012 в 14:32

    FeelGood, лучше поздно, чем никогда — CSS Box Alignment.

  14. Дмитрий 17 июня 2012 в 19:28

    Я, признаться, не понимаю такое поведение:
    http://jsfiddle.net/Rxu36/1/

    Ситуация:
    значение vertical-align у элемента span контролирует выравнивание содержимого своего родителя?

  15. Seva 20 июня 2012 в 12:15

    Нет, оно контролирует выравнивание самого span, но так как он выше чем высота строки то он растягивает её на нужную высоту, и располагается на нижней её границе, а чтобы это получилось он её как бы растягивает в верх, если бы был по центру то растянул бы в оба направления, текст остаётся на своём месте, если бы он был ниже чем строка то он бы никак ни влиял на соседний текст, он бы сам двигался и всё.

  16. Дмитрий 23 июня 2012 в 1:23

    Спасибо, я понял.
    Хотя такое псевдо-контроль можно использовать для выравнивания текста по центру, если известна высота контейнера.
    http://jsfiddle.net/Rxu36/5/

  17. skiff 1 марта 2013 в 13:31

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

  18. Эд 4 июня 2013 в 9:16

    Чтобы выровнять содержимое блока, надо задать свойство line-height. Тогда vertical-align будет выравнивать элементы внутри блока, как надо.

  19. 1 25 марта 2015 в 14:48

    Чтобы выровнять содержимое блока, надо задать свойство line-height. Тогда vertical-align будет выравнивать элементы внутри блока, как надо.

  20. Алекс 23 ноября 2015 в 18:12

    если сделать объект display: inline-block; или просто inline и задать свойство vertical-align: middle; содержимое тоже не выравнивается!!(

  21. Дмитрий 27 ноября 2015 в 1:03

    Подскажите, пожалуйста, как выровнять:
    Есть блок:

    В него помещено построчно три ссылки на шрифт (нестандартный).
    В CSS блоке:
    .nav li{display:inline;}
    Как бы я не ровнял, какие бы теги не применял, первое слово в линейке остается на пару-тройку пикселей ниже. Остальные в линию.

    Было: vertical-align, justify-content и много всякой отсебятины типа margins:0 ))
    Пробовал с изображениями с этим шрифтом: тоже самое.

    Буду крайне признателен за помощь!

  22. Алекс 14 февраля 2016 в 22:46

    Это свойство -- действительно одно из самых темных в CSS. Делалось наспех, под лозунгом "долой форматирование атрибутами HTML, Вы всё это теперь можете делать через CSS". Как известно, в HTML 3.x вертикальное выравнивание возможно только для ячеек таблицы (атрибут valign, выравнивается содержимое) и для рисунков (т. е. inline-block, атрибут align, выравнивается сам рисунок). Эти особенности и были тупо скомпилированы в одно css-свойство.
    Отсутствие удобных и понятных методов вертикального выравнивания вне таблиц -- одна из причин, по которой народ неохотно отказывается от табличной верстки.
    Вот простая задачка, с которой мне так и не удалось справиться без таблицы или введения элементов-хаков в HTML (что, на мой взгляд, куда хуже, чем table).
    text
    Нужно сделать, чтобы текст был справа от картинки. При этом и текст и картинка должны быть центрированы по вертикали. Текста может быть много, и в этом случае он должен растягивать div, а картинка -- центрироваться или мало, и тогда все должно быть наоборот.

  23. Алекс 14 февраля 2016 в 22:55

    Прошу прощения, тэги съелись. Вот HTML к задачке:
    "div" "img..." "p" text "/p" "/div"
    Заменил угловые скобки кавычками, писать через амперсенды очень уж муторно.

  24. Лариса 13 мая 2016 в 16:39

    спасибо за статью! очень помогла :)

  25. Александр 28 августа 2016 в 16:06

    Как было сказано выше, в случае если vertical-align применяется к ячейке таблицы, - то оно должно влиять именно на расположение содержимого этой ячейки, однако:

    <a href="https://jsfiddle.net/onqn8q6h/">https://jsfiddle.net/onqn8q6h/</a>
    

Перейти к началу