Css свойство vertical-align

Vertical-align

line-height оказывает влияние на высоту строки, но, надо признать, что это свойство скудно по своим возможностям. В CSS есть другое средство, которое намного интереснее. Представляю вам главного гостя на сегодняшнем вечере — vertical-align.

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

Но всё же, давайте по порядку.

baseline

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

middle

Вот здесь уже интереснее. Значение middle выравнивает середину бокса по середине строчных букв текста. Таким образом, «родительская» базовая линия оказывается на половину высоты строчных букв (так называемой «x-высоты», ей в CSS соответствует единица ex) ниже середины нашего бокса.

Сразу перейдём к примеру:

xxx 100×100 xxx

span {
	display: inline-block;
	width: 100px;
	height: 100px;
	background: #aa0;
	vertical-align: middle;
}
p {
	border: 1px solid #0a0;
}

И результат:

Нам уже известно, что высоту строки определяют самые высокие боксы в ней, поэтому наш инлайн-блок растянул строку ровно на 100px. У инлайн-блока стоит vertical-align в значении middle. Но, т.к. общая базовая линия идёт по нижнему краю букв «х», а положение середины элемента зафиксировано относительно положения базовой линии текста (на половину высоты строчных букв выше нее), то этой базовой линии приходится сместиться, подстраиваясь под самый высокий бокс.

Если говорить точнее, высота строки сейчас задается инлайн-блоком, но базовая линия абзаца привязана к отметке 50рх+ 0.5ex от верха (или 50рх – 0.5ex от низа). Инлайн-блок («высокая птица») немного подтянул базовую линию («проволоку»)как ему удобнее, но при этом остался к ней привязанным.

sub

Значение sub опускает базовую линию бокса на уровень, отведенный для нижних индексов родительского бокса (не влияя на размер шрифта элемента).

Пример:

xxx__100x100__xxx

p {
	border: 1px solid #0a0;
padding: 0 10px;
}
span {
	background: #88f;
}
i {
	display: inline-block;
	background: #aa0;
	vertical-align: sub;
}

Результат:

Я поставил подчёркивания, чтобы вы могли видеть базовую линию. Она осталась на своём месте, а вот элемент , у которого стоит vertical-align: sub — опустился вниз на отведённое место для нижних индексов. 

Что есть «Место нижних индексов»? Это уровень, отведенный для подстрочных индексов (как «двойка» в H2O), которые в HTML оформляются тегом . Точное значение их местоположения спецификация не определяет, так что браузеры и ОС имеют право на «немного самодеятельности» (а иногда и метрики шрифта могут на него повлиять).

text-top

Значение text-top выравнивает верхний край инлайн-бокса по верхнему краю области контента предка.

Смотрим пример:

xxx__100x100__xxx

span {
	background: #88f;
}
i {
	display: inline-block;
	background: #aa0;
	font-size: 16px;
        vertical-align: text-top;
}
p {
	border: 1px solid #0a0;
	font-size: 32px;
	padding: 0 10px;
}

И результат:

Я нарочно поместил в лайн-бокс картинку, чтобы вы могли увидеть ту самую контентную область  (которая не зависит от высоты строки), по верху которой и равняется элемент с text-top (оранжевый бокс в нашем случае). Это та самая контентная часть, которая  определяет высоту строки по дефолту. Браузер может, например, брать размер кегельной площадки или координаты максимальных верхних и нижних выносных элементов символов шрифта (см. предыдущие статьи).

Картинка лишь определила высоту строки, но высота контентной части при этом не изменилась. Картинка — это атомарный (неразрывный) инлайновый бокс со своими внутренними размерами и размер текста ей не указ, т.к. она не является буквой шрифта. Метрики шрифта родительского элемента влияют лишь на положение ее нижнего края, «стоящего» на базовой линии.

Вывод таков, что элементов с vertical-align: text-top не интересует верхний край строки, им важен верх области текста, и выравниваются они именно по нему.

text-bottom

Значение text-bottom аналогично text-top, только в отличие от последнего, выравнивает нижний край инлайн-бокса по нижнему краю области контента предка.

Шаг 3

И последнее что мы сделаем, это добавим кое-какие стили, чтобы страничка выглядела немного привлекательнее. Давайте начнём с меню.

Первое что мы сделали, чтобы меню выглядело лучше, удалили маркеры, установив атрибут list-style:none, а также установили внутренние и внешние отступы, так как по умолчанию в разных броузерах они сильно различаются.

Обратите внимание, что затем мы указали чтобы ссылки отбражадись как блочные элементы. Теперь, при выводе, они растягиваются по всей ширине элемента в котором они расположены

Другая интересная вещь, которую мы использовали для меню — это псевдо-классы :before и :after. Они позволяют вам добавить что-нибудь перед и после элемента. Это хороший способ добавлять иконки или символы, такие как стрелочка в конце каждой ссылки. Такой трюк не работает в Internet Explorer 7 и ниже.

Шаг 1

Всегда хорошо начинать с семантической разметки. Наша страница будет структурирована следующим образом:

  • #floater (чтобы выровнять контент по центру)
  • #centred (центральный элемент)
    • #side
      • #logo
      • #nav (список )
    • #content
  • #bottom (для копирайтов и всего такого)

Напишем следующую html-разметку:

Шаг 2

Сейчас мы напишем простейший CSS, для размещения элементов на странице. Вы должны сохранить этот код в файле style.css. Именно на него прописана ссылка в html-файле.

Перед тем как сделать наш контент выровненным по центру, необходимо для body и html установить высоту 100%. Так как высота считается без внутренних и внешних отступов (padding и margin), то мы устанавливаем их (отступы) в 0, чтобы не было скроллбаров.

Нижний отступ для элемента «floater»-а равен минус половине высоты контента (400px), а именно -200px;

Сейчас ваша страничка должна выглядеть приблизительно так:

Поскольку элементу #centered установлено position:relative, мы можем использовать абсолютное позиционирование элементов внутри него. Затем установим overflow:auto; для элемента #content, чтобы появлялись скроллбары, в случае если не будет помещаться контент.

Шаг 3

И последнее что мы сделаем, это добавим кое-какие стили, чтобы страничка выглядела немного привлекательнее. Давайте начнём с меню.

Первое что мы сделали, чтобы меню выглядело лучше, удалили маркеры, установив атрибут list-style:none, а также установили внутренние и внешние отступы, так как по умолчанию в разных броузерах они сильно различаются.

Обратите внимание, что затем мы указали чтобы ссылки отбражадись как блочные элементы. Теперь, при выводе, они растягиваются по всей ширине элемента в котором они расположены

Другая интересная вещь, которую мы использовали для меню — это псевдо-классы :before и :after. Они позволяют вам добавить что-нибудь перед и после элемента. Это хороший способ добавлять иконки или символы, такие как стрелочка в конце каждой ссылки. Такой трюк не работает в Internet Explorer 7 и ниже.

Шаг 4

Ну и самое последнее, мы добавим в наш дизайн кое-какие втили для ещё большей красоты.

В этих стилях мы устанавливаем закруглённые углы для элемента #centered. В CSS3, за это будет отвечать свойство border-radius. Это пока что не реализовано некоторыми броузерами, разве только использовать приставки -moz и -webkit для Mozilla Firefox и Safari/Webkit.

Совместимость

Как вы уже наверное предположили, основной источник проблем совместимости — Internet Explorer:

  • Элементу #floater обязательно надо установить ширину
  • В IE 6 лишние отступы вокруг меню

Целых девять свойств

Оказывается, для каждого объекта выравнивания — всего контента, всех элементов по умолчанию и отдельного элемента, его самого — есть пара свойств, одно из которых выравнивает по главной/строчной оси (в нашем примере — по горизонтали), а второе — по поперечной/блочной (в нашем примере — по вертикали). Получается 6 свойств — все комбинации из двух вариантов, по какой оси выравнивать, и трех — что именно выравнивать (контент, элементы или сам конкретный элемент). Вот они:

  • align-content
  • justify-content
  • align-items
  • justify-items
  • align-self
  • justify-self

See the Pen qrYobV by Ilya Streltsyn (@SelenIT) on CodePen.

В примере выше вы можете увидеть все 6 свойств в действии в гридах. Во флексбоксах работают только 4 наших старых знакомых: выравнивать отдельные элементы по главной оси там бессмысленно, поскольку всем пространством между ними уже заведует , и распределять после него уже нечего.

Но писать целых два свойства для выравнивания каждого объекта долго, нельзя ли как-нибудь покороче? Не так давно (в конце осени 2016-го) рабочая группа CSS задалась тем же вопросом и решила ввести для каждой пары / сокращенную запись. Над ее названием долго ломали голову и спорили, но в итоге победил вариант .

Так что в придачу к тем шести свойствам теперь есть еще три:

  • place-content
  • place-items
  • place-self

Значение каждого из них — комбинация значений align-* и justify-* через пробел. Например, или . Порядок (сначала вертикальное выравнивание, потом горизонтальное) соответствует порядку, в котором указываются, например, отступы (в записях типа ). Если указано только одно значение (например, ), оно копируется для обеих составляющих, по обеим осям.

Все 9 свойств уже работают, как минимум, в новых Firefox (52+). В Chrome до Canary 59 включительно сокращенные свойства () не работали, но (добавлено 25.05.2017) в Canary 60 они уже поддерживаются (хоть иногда и со странностями).

Не только флексбоксы

В недавней статье про новые возможности флексбоксов и CSS-гридов, когда они работают в связке, был короткий пример со свойством (и еще одним, но о нем чуть позже) для ячеек грида. А ниже — интерактивный пример, где вы можете сами сравнить действие всех четырех знакомых свойств в двух контейнерах с разными контекстами форматирования — флексбоксовом и гридовом:

See the Pen evKEMK by Ilya Streltsyn (@SelenIT) on CodePen.

Видите общий принцип?

Свойство определяет, что делать со свободным местом, оставшимся после размещения всего контента по горизонтали (точнее, по главной оси, зависящей от свойства , для флексбоксов, и по строчной оси, зависящей от направления текста, для гридов — но пока ограничимся простым случаем, как в примере). Оставить ли это место в конце строки (по умолчанию), переместить в начало (прижав контент к концу), раскидать поровну справа и слева от контента (тем самым отцентрировав его), раскидать поровну между элементами и т.д. Единственная разница, что в гриде элементы сгруппированы еще и по вертикали (по столбцам), поэтому и место поневоле распределяется именно между столбцами, а не самими элементами, как у флексбоксов.

A делает по сути то же самое, но по вертикали (точнее, по перпендикулярной оси для флексбоксов и по блочной оси для гридов, если совсем занудствовать). Здесь в обоих случаях контент у нас уже сгруппирован — в строки (во флексбоксах) или ряды (в гриде). И свободное место по вертикали может быть после всех этих строк/рядов, перед ним, поровну до и после них (и тогда они будут по центру), поровну между ними… Во флексбоксах (где, в отличие от гридов, нет ячеек с явными размерами) можно еще и равномерно растянуть высоту этих строк/рядов так, что свободного места не останется вообще.

Другими словами: свойства управляют всем контентом сразу, передвигая и раздвигая (если надо) то, во что этот контент сгруппирован: строки, ряды или колонки.

Ну а выравнивает именно «items», т.е. элементы — внутри строк флексбокса и рядов грида. А  — то же самое, но для каждого элемента в отдельности, и указывается для него самого. Первый задает поведение элементов по умолчанию, второй позволяет его переопределить.

Но как выравнивать элементы — все (по умолчанию) или некоторые по отдельности — по горизонтали, внутри колонок грида?

Страт (Strut)

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

В блоке всегда имеется «дефолтный» текстовый потомок, задающий шрифтовые параметры по умолчанию (в т.ч. line-height) для инлайнового содержимого этого блока. Если в блоке есть обычный текст, то в роли «дефолтного» текстового потомка выступает порождаемый этим текстом анонимный инлайновый бокс. Если же текста нет, то форматирование идет так, как если бы он был, как будто такой инлайновый бокс (с теми же свойствами) есть. Вот этот воображаемый инлайн и называется стратом – «Strut» (название навеяно редактором TeX).

Чтобы не запутать вас окончательно, приведу, пожалуй один наглядный пример:

div {
	border: 1px solid #000;
	padding:0 10px;
	font-size: 20px;
	background: #F90;
	width: 150px;
}
span {
		display: inline-block;
		width: 70px;
		height: 70px;
		background: #900;
	}

И сразу результат:

Итак, есть блок, в котором находится элемент (красный квадрат). Натурального текста в блоке нет, но вместо него там находится «воображаемый бокс», который и является нашим Strut’oм (на картинке я специально сделал его видимым). Т.е. текста в блоке нет, но он всё равно условно как бы есть. Так же, как и у обычного текста, у страта есть базовая линия, и его высота высчитывается метриками шрифта, о которых мы говорили в прошлых статьях.

Высота ‘a (инлайн-блока) заставляет лайн-бокс растягиваться, но при этом высота Strut’a не меняется. Вместо того, чтобы растянуться, он поднимается или опускается в зависимости от базовой линии самого блока, т.к. его базовая линия привязана к общей базовой линии строки.

Поговорим о свойстве CSS vertical align

Когда я только начинал работать в области веб-разработки, то немного помучился с этим свойством. Я думал, что оно должно работать, как классическое свойство “text-align”. Ах, если бы все было так просто…

CSS свойство vertical-align отлично работает с таблицами, но не с div или другими элементами. Когда вы используете его для div, то оно выравнивает элемент относительно других блоков, но не его содержимое. При этом свойство работает только с display: inline-block;.

Посмотрите пример

Мы хотим центрировать контент, а не сам div!

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

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

Взгляните на этот пример

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

Чтобы это работало, должен быть родительский контейнер с display: table, а внутри него – нужное количество столбцов, которое вы хотите центрировать с помощью display: table-cell и vertical-align: middle.

Посмотрите пример

Почему это работает с табличной разметкой, но не с элементами div? Потому что у строк в таблице одинаковая высота. Когда содержимое ячейки таблицы не использует все доступное пространство по высоте, браузер автоматически добавляет вертикальные отступы, чтобы центрировать содержимое.

Свойство position

Начнем с основ выравнивания по вертикали CSS div:

  • position: static — это значение по умолчанию. Элемент отображается в соответствии с порядком HTML;
  • position: absolute — используется, чтобы определить точное положение элемента. Эта позиция всегда связана с ближайшим относительно позиционированным родительским элементом (не static). Если не определить точное положение элемента, вы потеряете контроль над ним. Он отобразится случайно, полностью игнорируя поток документа. По умолчанию элемент отображается в левом верхнем углу;
  • position: relative — используется для позиционирования элемента относительно его нормального положения (статического). Это значение сохраняет порядок потока документа;
  • position: fixed — используется для позиционирования элемента относительно окна браузера, поэтому он всегда отображается в области просмотра.

Примечание: некоторые свойства (top и z-index) работают только в том случае, если для элемента задано значение position (не static).

Давайте приступим к делу!

Вы хотите осуществить CSS выравнивание по центру по вертикали? Сначала создайте элемент с относительной позицией и размерами. Например: 100% по ширине и высоте.

Второй шаг может быть различным в зависимости от целевых браузеров, но можно использовать один из двух вариантов:

  • Старое свойство: нужно знать точный размер окна, чтобы удалить половину ширины и половину высоты. Посмотрите пример;
  • Новое свойство CSS3: можно добавить свойство transform со значением translate 50% и блок всегда будет в центре. Посмотреть пример.

В принципе, если вы хотите центрировать контент, никогда не используйте top: 40% или left: 300px. Это прекрасно работает на тестовых экранах, но это не центровка.

Помните position: fixed? Можно сделать с ним то же самое, что и с абсолютной позицией, но вам не нужна относительная позиция для родительского элемента — она всегда будет позиционировать относительно окна браузера.

Вы слышали о спецификации flexbox?

Можно использовать flexbox. Это гораздо лучше, чем любой другой вариант выравнивания текста по центру CSS по вертикали. С flexbox управление элементами напоминает детскую игру. Проблема состоит в том, что нужно отбросить некоторые браузеры, такие как IE9 и версии ниже. Вот пример того, как вертикально центрировать блок:

Посмотреть пример

Используя flexbox расположение, можно центрировать несколько блоков.

Если вы примените то, что узнали из этих примеров, то сможете освоить CSS выравнивание блока по вертикали в кратчайшие сроки.

Ссылки и дополнительная литература

Изучение CSS разметки

FlexBox Froggy

Песочница flexbox

Данная публикация представляет собой перевод статьи «CSS Vertical Align for Everyone (Dummies Included)» , подготовленной дружной командой проекта Интернет-технологии.ру

Горизонтальное и вертикальное выравнивание

Вы можете комбинировать представленные выше техники для того чтобы получить идеально выравненные по центру элементы. Но обычно их можно разделить на 4 группы:

Выравнивание элемента с фиксированной шириной и высотой

Использование отрицательных отступов () равных половине этой ширины и высоты после абсолютного позиционирования элемента / выравняют элемент по центру. У этого способа достаточно хорошая кроссбраузерная поддержка:

Выравнивание элемента с неизвестной шириной и высотой

Если вы не знаете ширину или высоту элемента, то можете использовать свойство и отрицательный в в обоих направлениях (в зависимости от текущей ширины / высоты элемента) до центра:

Чтобы выровнять элемент по центру с помощью Flexbox вам нужно использовать два свойства центрирования:

Выравнивание элемента с помощью CSS Grid

Это просто небольшой трюк (присланный Lance Janssen), который в большей степени будет работать для одного элемента:

Вертикальное выравнивание

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

Выравнивание свойством line-height

В том случае, когда в блоке только одна строка, можно добиться ее выравнивания по вертикали, применив свойство «line-height» и установив ему желаемую высоту. Для надежности стоит установить еще и «height», значение которого будет равно значению «line-height», потому что последние поддерживается не во всех браузерах.

Это фиолетовая строчка, высота которой равна высоте блока.

.example-wrapper4{
line-height: 100px;
color: #DC09C0;
background: #E5DAE1;
height: 100px;
text-align: center;
}

Так же возможно добиться выравнивания блока с несколькими строками. Для этого придется использовать дополнительный блок-обертку, и устанавливать высоту строки ему. Внутренний блок может быть многострочным, но обязательно «inline». К нему нужно применить «vertical-align: middle».

А это inline-элемент. Здесь несколько оранжевыхстрочек. Они выравниваятсяза счет установленной высоты строки блока-родителя.

.example-wrapper5 {
line-height: 160px;
height: 160px;
font-size: ;
background: #FF9B00;
}

.example-wrapper5 .text1{
display: inline-block;
font-size: 14px;
line-height: 1.5;
vertical-align: middle;
background: #FFFAF2;
color: #FF9B00;
text-align: center;
}

У блока обертки должно быть установлено «font-size: 0». Если не установить нулевой размер шрифта, то браузер добавит от себя несколько лишних пикселей. Также придется указать размер шрифта и высоту строки для внутреннего блока, ведь эти свойства наследуются от родителя.

Выравнивание по вертикали в таблицах

Свойство «vertical-align» также действует на ячейки таблицы. C установленным значением «middle», контент внутри ячейки выравнивается по центру. Конечно, табличная верстка в наше время считается архаической, но в исключительных случаях можно симулировать ее, указав «display: table-cell».

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

осталось 10 шт

307грн.($14.05)

осталось 7 шт

267грн.($16.79)

.one_product .img_wrapper {
display: table-cell;
height: 169px;
vertical-align: middle;
overflow: hidden;
background: #fff;
width: 255px;
}

.one_product img {
max-height: 169px;
max-width: 100%;
min-width: 140px;
display: block;
margin: 0 auto;
}

Следует помнить, что если у элемента установлено «float» отличное от «none», то он в любом случае будет блочным (display: block) — тогда придется использовать дополнительный блок-обертку.

Выравнивание дополнительным inline-элементом

И для inline-элементов можно применить «vertical-align: middle». При этом все элементы с «display: inline», которые находятся в одной строке, выровняются относительно общей центральной линии.

Нужно создать вспомогательный блок с высотой, равной высоте родительского блока, тогда и желаемый блок выровняется по центру. Для этого удобно использовать псевдоэлементы :before или :after.

.example-wrapper6{
height: 300px;
text-align: center;
background: #70DAF1;
}


.pudge {
display: inline-block;
vertical-align: middle;
background: url(pudge.png);
background-color: #fff;
width: 200px;
height: 200px;
}


.riki { 
display: inline-block;
height: 100%;
vertical-align: middle;
}

Резюме

В этой статье мы доказали, что блочная сетка не такая уж и неподвластная. Как оказалось, это вполне управляемая конструкция. Мало того, красивое выравнивание блоков в сетке можно достичь совершенно обычным и не трудным способом, а результат позволяет нам легко использовать его плоды в любых проектах. Что я и делаю, когда предоставляется такая возможность.

Да, и конечно же, хочется выразить огромную благодарность Илье Стрельцыну () за его идеи и невероятную помощь в материалах. Без него бы этой статьи не было.

Обновление от 30.03.2017: Современное решение этой задачи на Grid Layout (без хаков и лишнего кода)

Ссылка на основную публикацию