ИКФ: Вертикальное выравнивание в строке, часть 3 (10-я публикация цикла “Тайны CSS2.1″)
vertical-align + line-height
Если вы внимательно читали предыдущие статьи, то уже наверняка поняли, как по отдельности работают vertical-align и line-height. Но как эти свойства взаимодействуют между собой? Краткий ответ – практически никак: их работа напрямую не пересекается. Задача vertical-align — сдвигать базовую линию, на сколько велено, а задача line-height (благодаря half-leading'ам) — отталкивать чужие лайн-боксы от этой базовой линии сверх метрик шрифта.
Детальную картину предлагаю разобрать на следующем примере:
<p> <span>Раз</span> <span>два</span> <span>три</span> <span class="four">четыре</span> <span>пять</span> </p>
span { vertical-align: baseline;background: #F90; } .four { line-height: 200px; vertical-align: 50px; } p { border: 1px solid #0a0; font-size: 32px; }
И результат:
Перед нами абзац с пятью инлайн-элементами, каждый из которых, по умолчанию, выстроен по общей базовой линии. Но, так как четвёртый инлайн-бокс, благодаря большому line-height (а соответственно half-leading'ам), самый высокий элемент в строке, остальные элементы вынуждены подстраиваться именно под него. Выходит, что именно четвёртый элемент рассказывает другим, где будет находиться общая базовая линия. На данный момент всё просто и уже знакомо, поэтому перейдём к главному.
Здесь стоит обратить внимание на следующие вещи. На смещение общей базовой линии (и, конечно же, вместе с ней всех элементов, кроме четвёртого) после того, как мы добавили к четвёртому элементу (с line-height) vertical-align в значении 50px и на то, как после этих действий совершенно не изменилась высота строки. И, главное, на сам четвёртый элемент, который в итоге этих взаимодействий остался на своём месте и его half-leading'и (помеченные красными стрелками) не изменились.
Суть в том, что vertical-align ничего не знает о line-height, а тот об vertical-align. Их вклад в итоговую высоту строки складывается уже по итогу, если необходимо. vertical-align отвечает за смещение инлайн-боксов, которые могут ездить вверх-вниз со всем, что у них есть — leading'и, и т.п. Если край их leading'ов при этом упрется в край лайн-бокса — лайн-бокс начнет растягиваться, а если не упрётся — ничего не произойдет, просто боксы сместятся друг относительно дружки.
Разные значения vertical-align + line-height
Главными вещами при взаимодействии vertical-align и line-height являются итоговая вертикальная координата элементов и конечная высота строки. Как в первом, так и во втором случаях результат может зависеть от разных значений vertical-align, из-за которых может поменяться начальная координата элементов и точка отсчёта самого line-height. И, если с абсолютными единицами в этом плане всё в принципе понятно, то результат от применения некоторых других значений может оказаться уже не таким очевидным.
Предлагаю посмотреть наглядный пример.
text-top + line-height
<p> <span>xxx_</span> <i>_100x100_</i> <span>_xxx</span> <img src="img.jpg"> </p>
span { background: #88f; } i { background: #aa0; font-size: 16px; vertical-align: text-top; line-height: 100px; } p { border: 1px solid #0a0; font-size: 32px; padding: 0 10px; }
И результат:
Уже знакомое нам значение vertical-align — text-top, выставленное элементу <i>, заставило его верхний край примыкать к верхней области самого контента. Эту ситуацию мы уже разбирали, поэтому ничего нового тут нет. Я прошу лишь обратить внимание на то, откуда начал свой отсчёт leading элемента <i>, после того, как мы добавили последнему свойство line-height в значении 100px. Начало его leading'a приходится на верхний край контентной части, которое совпадает с начальной координатой значения text-top.
Это типичная ситуация того, как после взаимодействия vertical-align и line-height вертикальная координата элементов и результативная высоты строки зависит от их значений. После всех манипуляций элемент <i> оторвался от верхнего края контентной части из-за верхнего half-leading'а, а уже нижним half-leading'ом растянул строку.
Чтобы увидеть другие варианты, я сделал специальную страницу-пример.
Другие публикации цикла
3. ИКФ: высота строки, часть 1 (3-я публикация цикла “Тайны CSS2.1″).
4. ИКФ: высота строки, часть 2 (4-я публикация цикла “Тайны CSS2.1″).
5. ИКФ: высота строки, часть 3 (5-я публикация цикла “Тайны CSS2.1″).
6. ИКФ: высота строки, часть 4 (6-я публикация цикла “Тайны CSS2.1″).
7. ИКФ: высота строки, часть 5 (7-я публикация цикла “Тайны CSS2.1″).
8. ИКФ: Вертикальное выравнивание в строке, часть 1 (8-я публикация цикла “Тайны CSS2.1″).
9. ИКФ: Вертикальное выравнивание в строке, часть 2 (9-я публикация цикла “Тайны CSS2.1″).
11. ИКФ: Горизонтальное выравнивание, часть 1 (11-я публикация цикла “Тайны CSS2.1″).
12. ИКФ: Горизонтальное выравнивание, часть 2 (12-я публикация цикла “Тайны CSS2.1″).
P.S. Это тоже может быть интересно:
Спасибо за такой превосходный по содержательности и наглядности материал. До вашей публикации руки не доходили так основательно углубиться в тему.
У меня у самого не доходили до этого цикла)))
Небольшое дополнение : http://jsfiddle.net/DjD9P/2/
Я правильно понимаю, что алкогоритм действий, в первом примере, примерно следующий:
1. берётся самая высокая строка (имеюшая line-height: 200px) она упирается своими ледингами и раздвигает лайн-бокс.
2. дальше смотрится где у неё vertical-align: 50px и БАЗОВУЮ ЛИНИЮ сдвигают ОТНОСИТЕЛЬНО этого инлайн-элемента на нужное значение.
То есть базовая линия для остальных элементов высчитывается в последнюю очередь и её высчитывают относительно элемента с самой большой высотой?
Более корректно сказать, что все элементы строки, привязанные к базовой линии, выстраиваются по ней, а потом алгоритм измеряет максимальные габариты строки (по самым высоким выступающим вверх и свисающим вниз частям) и располагает всю эту конструкцию под предыдущей строкой. Но да, получается, что положение базовой линии всей строки зависит от того элемента, у которого выступ над ней максимален.
Уже знакомое нам значение vertical-align — text-top, выставленное элементу , заставило его верхний край примыкать к верхней области самого контента.
Что-то не очень понятно. Его верхний край, насколько я вижу, примыкает к НИЖНЕЙ области остального контента.
И почему-то сдвинут вниз. Объясните, пожалуйста, по пунктам, как оно тут работает.
leading’a приходится на верхний край контентной части, которое совпадает с начальной координатой значения text-top.
откуда берётся значение этой координаты?
Как простраивалась базовая линия в теге span? (ну с имиджем, вроде, всё ясно, он, как бы, расположился на той же базовой линии, что и span)
Спасибо!
У элемента span проставлена очень большая line-height (100px). Это, а не высота закрашенного текста, и есть его высота с точки зрения алгоритма раскладки. Cверху и снизу у него две половинки leading-а, «добивающие» общую высоту до 100px (в первом приближении что-то вроде прозрачных padding-ов). И именно граница верхней половины leading-а выравнивается по верхней границе текста на синеватом фоне, а базовая линия смещается ровно настолько, сколько нужно для такого выравнивания.
Возможно, пример стал бы более понятным, если убрать изображение, или сделать два примера, сначала без изображения, потом с ним.
А без изображения, вроде, становится, более-менее ясно:
1. У нас есть элемент с большим line-height (100px). Именно он определяет итоговую высоту строки, на которой расположены все элементы.
2. Окрашенный (синим) текст определяется высотой шрифта. Окрашенные (зелёным) циферки, насколько мне понятно, является и высотой strut. Предположу что strut всё же совпадает с закрашенными цифрами, а не текстом, поскольку закрашенные цифры имеют самый большой line-height и поэтому остальные элементы подстраиваются под них. Картину пока в рассчёт не берём.
3. Поскольку значение vertical-align: text-top, то верхний край нашего элемента должен находится по верхнему краю текста. Но поскольку наш элемент самый высокий из-за line-height, то строка строится по нему, соответственно, к нашему элементу прибавляются leading-и нужного размера, а дальше к верху leading нашего элемента прикрепляются leading-и других элементов, который соответствуют размеру их шрифта (и совпадают с закрашеной областью текста). line-height позволяет расширить или сузить leading-и, в случае текста размер leading-и соответствуют размеру шрифта, в случае циферок они расширены до того, чтоб итоговая высота строки соответствовала line-height: 100px. Если же мы уберём line-height у нашего закрашенного элемента с цифрами, то он подвиснет по верхней стороне закрашенного текста. То есть, поскольку наш элемент с закрашенными цифрами меньше, чем элементы с закрашенным текстом, то наши циферки будут как бы висеть, на этой верхней линии, расположеной на верхней границе leading-ов закрашенного текста. Если же line-height циферок сделать ещё меньше, меньше размера шрифта (и, соответственно, высота строки циферок будет меньше закрашенной зелёным области), то циферки поднимутся ещё выше, потому что высота строки будет равна высоте line-height (а не закрашенной области) и именно она должна совпасть с верхней границей leading-ов закрашенного текста.
4. Теперь что касается картинки. Поскольку картинка не является текстом, то она просто располагается… на базовой линии strut? и расширяет размера блока, но оставляет размер строки не тронутым, поскольку это не текст?
В любом случае, не совсем понятно, где располагается strut строки с элементами, по базовой линии циферок или текста? Сначала мне казалось, что по циферкам, а теперь из-за картинки уже стало не совсем ясно.
И вообще, правильно ли я всё понял? Поправьте/добавьте, пожалуйста…
Спасибо!
В Ваших примерах(по ссылке), похоже, vertical-align: top или bottom + line-height, добавлен два раза. кстати, в нём, не совсем понятно, зачем нужно назначать свойства для span , i, когда для i оба свойства переназначаются.
В примерах интересна следующая особенность — размер закрашенного бокса может не совпадать, и почти никогда не совпадает с line-height. Но, скажем в проиллюстрируемом Вами (последнем в тексте) примере, понимание того, что text-top свойство для среднего блока «цепляется» за верх контентной области не своим закрашенным боксом, а именно своим line-height, а точнее, своим верхних half-leading’ом, показывает как браузер «видит строчки». А видит он их, похоже, так: именно средний «маленький» элемент, на самом деле большой, поскольку у него большой line-height (которого не видно на иллюстрации).
Второй момент — высота содержащего блока формируется исходя из элемента с самым большим line-height. А далее, vertical-align исходя уже из этого, подстраивает базовую линию strut.
Скажем, в примере по ссылке «vertical-align: (Абсолютные единицы) + line-height», если присмотреться по центру будет элемент с надписью 16px. Почему? Потому что у него самый большой line-height и он распирает своими half-leading’ми блок — дальше его half-leading’ов, в блоке ничего «не выпирает». А поскольку он «поднят» вверх на 16 пикселей над базовой линией, происходит обратное — базовая линия ОПУСКАЕТСЯ ОТНОСИТЕЛЬНО НЕГО на 16 пикселей.
Поэкспериментировал с примерами, вот что вышло https://jsfiddle.net/y2bvpnav/
Точнее вот https://jsfiddle.net/y2bvpnav/1/
вот правильная ссылка https://jsfiddle.net/y2bvpnav/1/