CSS-live.ru

ИКФ: высота строки, часть 3 (5-я публикация цикла «Тайны CSS2.1»)

line-height для инлайн-элементов

Элементы с display:inline, как мы уже знаем, создают инлайновые боксы. В главном они ведут себя так же, как обычный текст, но могут иметь собственный фон, границы и т.п. Как же влияет line-height на них? Это мы прямо сейчас и выясним.

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

Простейший пример:

<p><span>span</span></p>
	p {
		border: 1px solid #000;
		background: #F90;
		padding-left: 20px;
		width: 80px;
	}
	span {
		font-size: 30px;
		background: #FC6;
	}

И результат:

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

line-height меньше или больше размера шрифта

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

<p class="minus"><span>span</span></p>
<p class="plus"><span>span</span></p>
	p {
		border: 1px solid #000;
		background: #F90;
		padding-left: 10px;
		width: 80px;
		margin: 40px auto;

	}
	.minus span {
		font-size: 30px;
		background: #FC6;
		line-height: 10px;
	}

	.plus span {
		font-size: 30px;
		background: #FC6;
		line-height: 100px;
	}

Оба результата сразу:

Когда line-height инлайнов больше или меньше размера шрифта (площадок, вычисленных метриками), в дело вступают уже знакомые нам "leading" и, следовательно, half-leading-и с обеих сторон. В первом случае (отрицательном) они уменьшают высоту строки из-за того, что half-leading-и у площадок становятся отрицательными, а во втором (положительном) наоборот – увеличивают строку по высоте, добавив при этом лишние "свинцовые бруски" к нашим площадкам. В общем, всё тоже самое, что и с обычным текстом.

Ну, и конечно же, в случае с маленьким line-height не следует забывать о наложении строк.

line-height + границы и отступы

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

В последнем коде я сделал некоторые изменения, добавив к нашим инлайн-элементам padding и border

	p {
		border: 1px solid #000;
		background: #F90;
		padding-left: 10px;
		width: 100px;
		margin: 40px auto;

	}
	.minus span {
		font-size: 30px;
		background: #FC6;
		line-height: 10px;
		padding: 100px 0;
		border: 10px solid #000;
	}

	.plus span {
		font-size: 30px;
		background: #FC6;
		line-height: 100px;
		padding: 100px 0;
		border: 10px solid #000;
	}

И вот что получилось:

Визуально может показаться, что отступы и границы расширили по высоте сами площадки, но это не так. На самом деле площадки остались той же высоты, что и были после расчёта метрик шрифта, а padding и border добавили к ним лишь визуальные фон и границы, не влияя при этом на их положение по вертикали.

Грубо говоря, мы имеем следующее: полоску с границей (border), далее идёт полоска пространства с фоном (padding), потом сама площадка, потом опять пространство с фоном (padding), ну и завершает всю эту конструкцию снова граница (border).

Вследствие чего можно сделать вывод, что "leading" и (padding или border) — это совершенно разные вещи, которые никак не пересекаются, не относятся друг к другу и выполняют в строке, каждый свои функции. Например, padding визуально добавляет к площадке место с тем же фоном, но на положение по вертикали не влияет, а вот "leading", наоборот, влияет только на положение площадок и на сдвиг их координат.

Высота строки при разных инлайн-боксах и line-height

Мы выяснили, как вычисляется высота строки, если в ней содержится всего лишь один инлайн-элемент, но какова будет она, если скажем лайн-бокс будет состоять не только из инлайн-элемента, но ещё и какого-нибудь текста или другого инлайна?

Разберём на примере:

<p> Before <span> Span Text Span</span> After </p>
p {
	border: 1px solid #000;
	background: #F90;
	padding-left: 10px;
	width: 400px;
	line-height: 50px;
	font-size: 40px;
}
	p span {
		background: #FC6;
		line-height: 150px;
		font-size: 12px;
	}

Посмотрим результат:

Ситуация следующая. Есть строка, в которой содержатся два анонимных инлайн-бокса (текста) и "натуральныйинлайн-бокс (инлайн-элемент <span>). Последний, надо заметить, находится ровно по середине. Примерные площадки у текста и инлайн-элемента я выделил специальными цветами для того, чтобы вы могли лучше представить происходящее. Не смотря на то, что сам текст и его площадки явно превышают по высоте площадку инлайн-элемента, они вынуждены подстраиваться именно под него, а не наоборот. Почему так происходит? Давайте разберёмся…

Дело в том, что дефолтное поведение лайн-боксов в блоке определяется размером шрифта (font-size) и высотой строки (line-height), указанным для самого блока (или теми значениями font-size и line-height, которые выходят для блока по итогу всех каскадов и наследований), а всё, что внутри — переопределяется. Исключения вынуждены приспосабливаться под общие правила. В нашем случае исключением является инлайн-элемент, потому что его размеры шрифта и высота переопределены и явно отличаются от шрифта и высоты строки самого блока. Несмотря на свои малые размеры, он выстроился по базовой линии, которая берётся по основному тексту. Именно такое поведение "исключений" и является подстраиванием под общие правила.

font-size нашего блока равен 40pxline-height 50px, а это означает, что высота текста в блоке будет 50px, включая площадки и "leading". Но почему же тогда общая высота строки у нас получилась 150px? А всё дело в том, что в таком поведении лайн-бокса виновато именно наше "исключение" (инлайн-элемент). У последнего выставлен line-height в значении 150px, что заставляет его "leading" распирать строку. Следовательно, высота инлайн-элемента теперь становится больше родительского лайн-бокса, и он в итоге и определяет фактическую высоту общей строки, центрируется в ней и подтягивает за собой базовую линию всей строки.

Базовая линия  это своего рода проволока, на которой сидят все «буквы-птицы», независимо от их размера. И только в самом высоком инлайн-боксе буквы не могут двигаться, т.к. жёстко зафиксированы half-leading-ами  (чтобы обеспечить требуемый line-height) и поэтому двигаться приходится всем остальным буквам. За счёт чего и происходит "подтягивание" общей базовой линии.

Отсюда можно сделать вывод, что сколько бы инлайн-боксов не находилось в строке, её высота будет определяться самым высоким из них.

Другие публикации цикла

1. Введение в инлайновый контекст форматирования (ИКФ): основные понятия (1-я публикация цикла “Тайны CSS2.1″).

2Введение в инлайновый контекст форматирования (ИКФ): основные понятия (2-я публикация цикла “Тайны CSS2.1″).

3ИКФ: высота строки, часть 1 (3-я публикация цикла “Тайны CSS2.1″).

4ИКФ: высота строки, часть 2 (4-я публикация цикла “Тайны CSS2.1″).

6. ИКФ: высота строки, часть 4 (6-я публикация цикла “Тайны CSS2.1″).

7ИКФ: высота строки, часть 5 (7-я публикация цикла “Тайны CSS2.1″).

8ИКФ: Вертикальное выравнивание в строке, часть 1 (8-я публикация цикла “Тайны CSS2.1″).

9ИКФ: Вертикальное выравнивание в строке, часть 2 (9-я публикация цикла “Тайны CSS2.1″).

10. ИКФ: Вертикальное выравнивание в строке, часть 3 (10-я публикация цикла “Тайны CSS2.1″).

11ИКФ: Горизонтальное выравнивание, часть 1 (11-я публикация цикла “Тайны CSS2.1″).

12ИКФ: Горизонтальное выравнивание, часть 2 (12-я публикация цикла “Тайны CSS2.1″).

Нам необходимы ваши конструктивные коментарии в наших статьях! Пожалуйста, не проходите мимо.

P.S. Это тоже может быть интересно:

13 комментариев

  1. Спасибо большое за этот цикл статей. Единственное, было бы удобнее, если бы в ранние статьи в раздел "Другие публикации цикла" добавить ссылки на следующие уже вышедшие материалы цикла.

  2. Визуально может показаться, что отступы и границы расширили по высоте сами площадки, но это не так. На самом деле площадки остались той же высоты, что и были после расчёта метрик шрифта, а padding и border добавили к ним лишь визуальные фон и границы, не влияя при этом на их положение по вертикали.

    Если это сделали для упрощения жизни верстальщиков, то это ппц! Это же не логично. А не логичное не слишком часто упрощает жизнь.

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

    https://jsfiddle.net/Launder/gmg3u1tL/2/

    span вылезает вверх, при этом размер блока, что в Мозиле, что в Хроме, не меньше какого-то определённого размера (наверняка это как-то связано со шрифтом). Интересно отследить положение спана, относительно блока, между ситуациями когда размер шрифта и лайн-хейт численно совпадает(по факту шрифтовые площадки немного больше) и когда лайн-хейт намного меньше шрифтовых площадок.
    Если мы сравним третий пример со вторым, в котором размер блока зависит от шрифтовых площадок, и распирается ими, то в третьем, где размер блока зависит от размера лайн-хейт (который численно равен размеру шрифта), шрифтовые площадки выходят за размеры блока, похоже, в равной степени. Или, как и указана в статье, халф-лидинги сверху и снизу равны и отрицательны.
    Но если сравнить третий с четвёртым примером, в котором размер лайн-хейт существенно меньше шрифтовых площадок, то можно увидеть, что расположение спана относительно нижней границы блока не изменилось — он выходит за неё на незначительное расстояние (Проверял в Хроме и Лисе). При этом базовая линия явно выше нижнего края блока. От чего зависит и откуда берётся это расстояние выхода спана за нижнюю границу блока — непонятно. По крайней мере от толщины границы блока оно не зависит. А сверху блок уменьшается, в результате чего, как я уже сказал, спан вылезает за границу блока.
    ЗЫ: добавил перенос строки + span в четвёртый пример, где лайн-хейт значительно меньше шрифтовых площадок. Блок увеличился (понятно, теперь его же растягивают два лайн-хейт-а). Понятно также что строчки налезают одна на другой, как и указано в статье. Но, что интересно, что в Хроме, что в Лисе, то, насколько шрифтовые площадки вылезают вверх вниз соответственно, не зависит от количества строк. Отсюда можно сделать предположение, что для определённого размера шрифтовых площадок, есть минимальный лайн-хейт (о чём Вы писали в статье что броузеры так поступают), но есть также и определённое расстояние, на которое вылезает спан из блока как снизу, так и сверху — снизу чуть-чуть, сверху заметно. Похоже, соотношения шрифтовым площадок с минимальным лайн-хейтом и этими расстояниями величина постоянная для браузера. А если сравнить резульат Хрома и Лисы, то разница если и есть, то практически не заметна.

    1. https://jsfiddle.net/Launder/gmg3u1tL/2/

      4ый пример, смотрел на Хроме и Лисе.

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

  4. Сначала строка с большим шрифтом, потом, с маленьким:
    https://jsfiddle.net/Launder/h0bs30q0/2/

    откуда тут берётся межстрочное расстояние (расстояние между текстовыми площадками)?
    Оно постоянно, вне зависимости от того куда мы поставим перенос строки(br), внутрь спана big, внутрь спана small или поставим между ними…

    поменяем спаны местами:
    https://jsfiddle.net/Launder/24wj22yd/

    аналогично, меняем положение переноса строки (br). Первое, относительно предыдущего примера оно стало меньше. Второе, когда перенос внутри маленького спана, строка сдвигается чуть-чуть вверх, по сравнению, с тем, когда перенос внутри большого спана или между спанами. Межстрочное расстояние, когда перенос внутри маленького спана, минимально, когда мы ставим перенос внутрь большого или между спанами, похоже всё-таки добавляет один пиксель(в итоге получается два пискселя).
    Не могли бы Вы объяснить поведение строчек в данных примерах?
    Спасибо!

Добавить комментарий для Алексей Отменить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *

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