Каким свойством css можно задать высоту строки текста

Каким свойством css можно задать высоту строки текста thumbnail

Как настроить высоту строки в CSS

От автора: CSS line-height — это, вероятно, один из самых неправильно понимаемых, но часто используемых атрибутов. Как дизайнеры и разработчики, когда мы думаем о line-height, мы можем представить концепцию направляющих в полиграфическом дизайне — термин, достаточно интересный, который происходит от буквального помещения направляющих между строками шрифта.

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

Обзор типографских терминов

В традиционном западном дизайне строка текста состоит из нескольких частей:

Базовая линия: это воображаемая линия, на которой находится текст. Когда вы пишете в блокноте с разметкой, базовая линия — это строка, на которой вы пишете.

Нижняя линия: эта линия находится чуть ниже базовой линии. Это линия, которой касаются некоторые символы — такие как прописные g, j, q, y и p.

Каким свойством css можно задать высоту строки текста

Практический курс по верстке адаптивного сайта с нуля!

Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3

Узнать подробнее

Высота X: это (очевидно) высота обычной строчной буквы x в строке текста. Как правило, это высота других строчных букв, хотя некоторые из них могут иметь части символов, которые будут превышать x-высоту. Для всех намерений и целей, это считается воспринимаемой высотой строчных букв.

Высота заглавных букв: это высота большинства заглавных букв в данной строке текста.

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

Как настроить высоту строки в CSS

Каждая из частей текста, описанных выше, является неотъемлемой частью самого шрифта. Шрифт разработан с учетом каждой из этих частей; тем не менее, есть некоторые части типографики, которые оставлены на усмотрение разработчика (как вы и я!), а не дизайнера. Одной из них является направляющие.

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

Как настроить высоту строки в CSS

Разработчик CSS может подумать: «Хорошо, направляющая — это высота строки, давайте двигаться дальше». Хотя эти два понятия взаимосвязаны, они также отличаются в некоторых очень важных аспектах. Давайте возьмем пустой документ и добавим к нему классический «сброс CSS»:

* {

  margin: 0;

  padding: 0;

}

Это удаляет поля и отступы для каждого элемента. Мы также будем использовать Lato от Google Fonts в качестве font-family. Нам понадобится некоторый контент, поэтому давайте создадим тег h1 с некоторым текстом и установим для его line-height что-то ужасно огромное, например 300px. В результате получается одна строка текста с удивительным количеством места над и под строкой.

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

Как настроить высоту строки в CSS

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

Что еще более удивительно, так это то, что при явной установке элемента line-height и font-size для одного и того же значения будет оставлено дополнительное пространство над и под текстом. Мы можем увидеть это, добавив цвет фона к элементам.

Это связано с тем, что даже если для параметра font-size установлено значение 32px, фактический размер текста является чем-то меньшим, чем это значение из-за созданного поля.

Научить CSS рассматривать высоту строки как направляющие

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

Направляющие можно задать в CSS довольно просто. Майкл Таранто выпустил инструмент под названием Basekick, который решает эту проблему. Это достигается путем применения отрицательного верхнего поля к псевдо-элементу ::before и translateY к самому элементу. Конечным результатом является строка текста без лишних пробелов вокруг нее.

Самую актуальную версию формулы можно найти в исходном коде для Системы проектирования Braid от SEEK. В приведенном ниже примере мы пишем миксин Sass, чтобы он выполнял вычисления, но ту же формулу можно использовать с миксинами JavaScript, Less, PostCSS или чем-то еще, что предоставляет такие математические функции.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

@function calculateTypeOffset($lh, $fontSize, $descenderHeightScale) {

  $lineHeightScale: $lh / $fontSize;

  @return ($lineHeightScale — 1) / 2 + $descenderHeightScale;

}

@mixin basekick($typeSizeModifier, $baseFontSize, $descenderHeightScale, $typeRowSpan, $gridRowHeight, $capHeight) {

  $fontSize: $typeSizeModifier * $baseFontSize;

  $lineHeight: $typeRowSpan * $gridRowHeight;

  $typeOffset: calculateTypeOffset($lineHeight, $fontSize, $descenderHeightScale);

  $topSpace: $lineHeight — $capHeight * $fontSize;

  $heightCorrection: 0;

  @if $topSpace > $gridRowHeight {

    $heightCorrection: $topSpace — ($topSpace % $gridRowHeight);

  }

  $preventCollapse: 1;

  font-size: #{$fontSize}px;

  line-height: #{$lineHeight}px;

  transform: translateY(#{$typeOffset}em);

  padding-top: $preventCollapse;

  &::before {

    content: «»;

    margin-top: #{-($heightCorrection + $preventCollapse)}px;

    display: block;

    height: 0;

  }

}

Каким свойством css можно задать высоту строки текста

Практический курс по верстке адаптивного сайта с нуля!

Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3

Узнать подробнее

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

$baseFontSize: Это нормальный font-size для нашей системы, на основе которого все остальное будет управляться. Мы будем использовать 16px в качестве значения по умолчанию.

$typeSizeModifier: Это множитель, который используется вместе с базовым размером шрифта для определения правила font-size. Например, значение 2 в сочетании с базовым размером шрифта 16 пикселей даст нам font-size: 32px.

$descenderHeightScale: Это высота нижней линии шрифта, выраженная в виде отношения. Для Lato это примерно 0,11.

$capHeight: Это конкретная высота шрифта, выраженная в виде отношения. Для Lato это около 0,75.

$gridRowHeight: В макетах по умолчанию обычно используется вертикальный ритм, что обеспечивает комфортное чтение. Например, все элементы на странице могут быть разнесены на четыре или пять пикселей. Мы будем использовать 4 в качестве значения, потому что оно легко делится на нашу $baseFontSize 16px.

$typeRowSpan: Как и $typeSizeModifier, эта переменная служит множителем, который будет использоваться с высотой строки сетки для определения значения правила line-height. Если наша высота строки сетки по умолчанию равна 4, а диапазон строк текста равен 8, это дает нам значение line-height: 32px.

Читайте также:  На каких свойствах веществ основаны данные способы разделения смесей

Теперь мы можем вставить эти числа в формулу Basekick выше (с помощью функций SCSS и миксинов), и это даст нам приведенный ниже результат.

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

Уточнение кода

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

Как настроить высоту строки в CSS

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

$baseFontSize: 16;

$gridRowHeight: 4;

@mixin basekick($typeSizeModifier, $typeRowSpan, $descenderHeightScale, $capHeight) {

  /* Same as above */

}

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

@mixin Lato($typeSizeModifier, $typeRowSpan) {

  $latoDescenderHeightScale: 0.11;

  $latoCapHeight: 0.75;

  @include basekick($typeSizeModifier, $typeRowSpan, $latoDescenderHeightScale, $latoCapHeight);

  font-family: Lato;

}

Теперь, переменные на основе правил, мы можем вызывать миксин Lato без особых проблем:

.heading—medium {

  @include Lato(2, 10);

}

Этот вывод дает нам правило, которое использует шрифт Lato с font-size 32px и line-height 40px со всеми соответствующими переводами и полями. Это позволяет нам писать простые правила стилей и использовать согласованность сетки, к которой привыкли дизайнеры при применении таких инструментов, как Sketch и Figma.

В результате мы можем без особых усилий создавать идеальные до пикселям дизайны. Посмотрите, насколько хорошо пример выровнен с нашей базовой сеткой 4px ниже. (Вам, вероятно, придется увеличить масштаб, чтобы увидеть сетку.)

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

Двигаясь к стандарту

Хотя, чтобы научить CSS вести себя, как инструменты дизайна, потребует немного усилий, свет в конце туннеля уже виден. Также предложено дополнение к спецификации CSS для естественного переключения этого поведения. Предложение в его нынешнем виде добавит дополнительное свойство к текстовым элементам, похожим на line-height-trim или leading-trim.

Автор: Caleb Williams

Источник: https://css-tricks.com

Редакция: Команда webformyself.

Каким свойством css можно задать высоту строки текста

Практический курс по верстке адаптивного сайта с нуля!

Изучите курс и узнайте, как верстать современные сайты на HTML5 и CSS3

Узнать подробнее

Каким свойством css можно задать высоту строки текста

PSD to HTML

Верстка сайта на HTML5 и CSS3 с нуля

Смотреть

Источник

line-height и vertical-align — это простые свойства CSS. Настолько простые, что большинство из нас уверены, что понимают, как они работают и как их использовать. К сожалению, это не так — на самом деле они, пожалуй, являются самыми сложными свойствами, поскольку играют важную роль в создании малоизвестной особенности CSS под названием «строчный контекст форматирования» (inline formatting context).

Например, line-height можно задать в виде длины или безразмерного значения, но его значение по умолчанию — normal (стандартное). Хорошо, но что значит «стандартное»? Зачастую пишут, что это (как правило) 1, или, может быть, 1,2. Даже в спецификации CSS нет четкого ответа на данный вопрос.

Нам известно, что безразмерное значение line-height зависит от значения font-size, но проблема в том, что font-size: 100px выглядит по-разному для разных гарнитур. В связи с этим возникает вопрос: всегда ли line-height будет одинаковым или может различаться? Действительно ли это значение находится в промежутке от 1 до 1,2? А как vertical-align влияет на line-height?

Давайте углубимся в не самый простой механизм CSS…

Начнем с разговора о font-size

Рассмотрим этот простой HTML-код с тегом p, содержащим три элемента span, каждый из которых со своим font-family:

<p>
<span class=»a»>Ba</span>
<span class=»b»>Ba</span>
<span class=»c»>Ba</span>
</p>
p { font-size: 100px }
.a { font-family: Helvetica }
.b { font-family: Gruppo }
.c { font-family: Catamaran }

При использовании одного и того же font-size в разных гарнитурах высота получается различной:

Даже если нам известно об этой особенности, почему font-size: 100px не создает элементы высотой 100px? Я измерил эти значения: Helvetica — 115px, Gruppo — 97px и Catamaran — 164px.

Хотя на первый взгляд это выглядит несколько странно, все вполне ожидаемо — причина в самом шрифте. Как это работает:

  • Шрифт задает свой em-квадрат (em-square) (он же UPM, units per em — единиц на кегельную площадку) — своего рода площадку, в рамках которой будет рисоваться каждый символ. В этом квадрате для измерения используются относительные единицы, и, как правило, для него принимаются размеры 1000 единиц. Хотя также бывает 1024, 2048 или иное количество единиц.
  • В зависимости от количества относительных единиц задаются метрики шрифтов, такие как высота верхних и нижних выносных элементов (ascender/descender), прописных и строчных букв. Некоторые значения могут выходить за рамки em-квадрата.
  • В браузере относительные единицы масштабируются до необходимого font-size.

Возьмем шрифт Catamaran и откроем его в FontForge для получения метрик:

  • em-квадрат принят за 1000 единиц;
  • высота верхних выносных элементов составляет 1100 единиц, а нижних — 540.

После нескольких проверок выяснилось, что браузеры на Mac OS используют значения HHead Ascent/Descent, а на Windows — Win Ascent/Descent (эти значения могут различаться). Помимо этого, высота прописных букв Capital Height составляет 680 единиц, а строчных X height — 485.

Таким образом, шрифт Catamaran использует 1100 + 540 единиц в em-квадрате, состоящем из 1000 единиц, и поэтому при размере font-size: 100px получается высота 164px. Данная вычисленная высота определяет область содержимого (content-area) элемента (этот термин будет использоваться далее по тексту). Можете считать область содержимого областью, к которой применяется свойство background.

Можно также предположить, что высота прописных букв составляет 68px (680 единиц), а строчных (x-высота) — 49px (485 единиц). В результате 1ex = 49px и 1em = 100px, а не 164px (к счастью, em зависит от font-size, а не от вычисленной высоты).

Прежде чем нырнуть глубже, рассмотрим основные моменты, с которыми придется столкнуться. Элемент p при отображении на экране может состоять из нескольких строк с соответствующей шириной. Каждая строка состоит из одного или нескольких строчных элементов (inline elements)(HTML-тегов или анонимных строчных элементов для текстового содержимого) и называется контейнером строки (line-box). Высота контейнера строки зависит от высот его дочерних элементов. То есть браузер вычисляет высоту каждого строчного элемента, а по ней — высоту контейнера строки (от самой верхней до самой нижней точки ее дочерних элементов). В результате высоты контейнера строки всегда достаточно, чтобы вместить все его дочерние элементы (по умолчанию).

Каждый HTML-элемент на самом деле представляет собой стопку контейнеров строки. Если вам известна высота всех контейнеров строки, то известна и высота элемента.

При изменении приведенного выше HTML-кода следующим образом:

Читайте также:  Какие физические и химические свойства металлов

<p>
Good design will be better.
<span class=»a»>Ba</span>
<span class=»b»>Ba</span>
<span class=»c»>Ba</span>
We get to make a consequence.
</p>

будет сгенерировано три контейнера строки:

  • в первом и последнем будет по одному анонимному строчному элементу (текстовое содержимое);
  • во втором будет два анонимных строчных элемента и 3 элемента span.

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

Сложным моментом в создании контейнера строки является то, что мы, по сути, не можем ни увидеть, ни управлять им через CSS. Даже применение фона к ::first-line не помогает отобразить высоту первого контейнера строки.

line-height: о проблемах и прочих вопросах

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

Даже если это может показаться странным, у строчного элемента есть две различных высоты: высота области содержимого и высота виртуальной области (virtual-area) (я сам придумал термин «виртуальная область», поскольку эту высоту мы увидеть не можем; в спецификации этого термина вы не найдете).

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

Кроме того, сказанное опровергает распространенное мнение о том, что line-height — это расстояние между базовыми линиями (baseline). В CSS это не так.

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

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

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

Есть и другие виды строчных элементов:

  • замещаемые строчные элементы (img, input, svg и т. д.);
  • inline-block и все элементы типа inline-*;
  • строчные элементы, которые задействованы в особом контексте форматирования (например, в элементе flexbox все flex-компоненты блокофицируются).

Для таких особых строчных элементов высота рассчитывается на основе их свойств height, margin и border. Если для height указано значение auto, то применяется line-height, и высота области содержимого равна line-height.

И все же проблема остается прежней: каково значение normal для line-height? Ответ на этот вопрос, как и в случае вычисления области содержимого, нужно искать среди метрик шрифта. Итак, вернемся к FontForge. Размер em-квадрата для Catamaran равняется 1000, но мы наблюдаем много значений для верхних и нижних выносных элементов:

  • Общие значения Ascent/Descent: высота верхнего выносного элемента — 770, нижнего — 230. Используются для создания символов (таблица «OS/2»).
  • Метрики Ascent/Descent: высота верхнего выносного элемента — 1100, нижнего — 540. Используются для определения высоты области содержимого (таблицы «hhea» и «OS/2»).
  • Метрика Line Gap (междустрочный интервал). Используется для определения line-height: normal, данное значение прибавляется к метрикам Ascent/Descent (таблица «hhea»).

В нашем случае шрифт Catamaran определяет, что междустрочный интервал равен 0 единиц, и, таким образом, line-height: normal будет равняться области содержимого, которая составляет 1640 единиц или 1,64.

В качестве сравнения: для шрифта Arial em-квадрат равен 2048 единиц, высота верхнего выносного элемента — 1854, нижнего — 434, междустрочный интервал — 67. Таким образом, при font-size: 100px область содержимого составит 112px (1117 единиц), а значение line-height: normal — 115px (1150 единиц или 1,15). Все эти метрики индивидуальны для каждого шрифта и задаются дизайнером шрифта.

Следовательно, задавать line-height: 1 неэффективно. Напомню вам, что безразмерные значения зависят от font-size, а не от области содержимого, а то, что размер области содержимого превышает размер виртуальной области, является причиной множества наших проблем.

Но причина не только в line-height: 1. Если уж на то пошло, из 1117 шрифтов, установленных на моем компьютере (да, я установил все шрифты из Google Web Fonts), у 1059 шрифтов, то есть в 95%, вычисленный показатель line-height больше 1. Вообще, их вычисленный показатель line-height варьируется от 0,618 до 3,378. (Вам не показалось — 3,378!)

Небольшие подробности по поводу расчета line-box:

  • Для строчных элементов — padding и border увеличивают область фона, но не высоту области содержимого (и не высоту контейнера строки). Поэтому область содержимого — это не всегда то, что видно на экране. От margin-top и margin-bottom нет никакого эффекта.
  • Для замещаемых строчных элементов, элементов типа inline-block и блокофицированных строчных элементов — padding, margin и border увеличивают height и, следовательно, высоту области содержимого и контейнера строки.

vertical-align: то свойство, которое управляет всем

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

Его значение по умолчанию — baseline. Помните такие метрики шрифта, как высота верхнего и нижнего выносных элементов (ascender/descender)? Эти значения определяют, где находится базовая линия и, следовательно, соотношение между верхней и нижней частями. Поскольку соотношение между верхним и нижним выносными элементами редко бывает 50/50, это может приводить к неожиданным результатам, например с элементами того же уровня.

Читайте также:  Какие свойства воздуха и воды используют люди

Начнем с такого кода:

<p>
<span>Ba</span>
<span>Ba</span>
</p>
p {
font-family: Catamaran;
font-size: 100px;
line-height: 200px;
}

Тег p с двумя одноуровневыми элементами span, наследующими font-family, font-size и фиксированную line-height. Базовые линии совпадают, и высота контейнера строки равна их line-height.

Но что, если у второго элемента font-size будет меньше?

span:last-child {
font-size: 50px;
}

Как бы странно это ни звучало, выравнивание базовой линии, выставленной по умолчанию, может привести к увеличению высоты (!) контейнера строки, как показано на рисунке ниже. Напоминаю, что высота контейнера строки рассчитывается от самой верхней до самой нижней точки его дочерних элементов.

Это могло бы стать доводом в пользу безразмерных значений line-height, но иногда требуются фиксированные значения для создания идеального вертикального ритма. Честно говоря, независимо от того, что вы выберете, у вас всегда будут проблемы с выравниванием строки.

Рассмотрим еще один пример. Тег p с line-height: 200px, который содержит один единственный span, наследующий его line-height

<p>
<span>Ba</span>
</p>
p {
line-height: 200px;
}
span {
font-family: Catamaran;
font-size: 100px;
}

Какова высота контейнера строки? Мы могли бы предположить, что 200px, но это не так. Проблема в том, что у p есть свое собственное, отличающееся значение font-family (по умолчанию это serif). Базовые линии тега p и span, по всей вероятности, находятся на разной высоте, и поэтому высота контейнера строки больше, чем предполагалось. Это вызвано тем, что браузеры производят вычисление, считая, что каждый контейнер строки начинается с символа нулевой ширины, который в спецификации называется «strut».

Невидимый символ с видимым эффектом.

Итак, у нас все та же проблема, что и в случае с одноуровневыми элементами.

С выравниванием по базовой линии все плохо, но, может, нас спасет vertical-align: middle? Как сказано в спецификации, middle «выравнивает контейнер по вертикальной средней точке (midpoint) с базовой линией родительского контейнера плюс половина x-высоты первичного элемента». Соотношение базовых линий, равно как и x-высот (x-height), может быть различным, поэтому на выравнивание по middle тоже нельзя положиться. А хуже всего тот факт, что в большинстве сценариев middle никогда не бывает по-настоящему «по центру». На это влияет слишком много факторов, которые нельзя задать через CSS (x-высота, соотношение верхнего и нижнего выносных элементов и др.).

Помимо этого, есть еще четыре значения, которые в некоторых случаях могут оказаться полезными:

  • vertical-align: top / bottom — выравнивание по верхней или нижней границе контейнера строки;
  • vertical-align: text-top / text-bottom — выравнивание по верхней или нижней границе области содержимого.

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

И наконец, vertical-align также принимает числовые значения, которые смещают контейнер выше или ниже относительно базовой линии. Этот последний вариант может пригодиться.

CSS восхитителен

Мы обсудили вопрос взаимодействия line-height и vertical-align, но сейчас вопрос в том, можно ли управлять метриками шрифта через CSS? Если кратко, то нет. Хотя я бы этого очень хотел. В любом случае, думаю, настало время немного развлечься. Метрики шрифта являются постоянными величинами, поэтому хоть что-то у нас должно получиться.

Что, если, например, нам нужен текст шрифтом Catamaran с высотой прописных букв ровно 100px? Вроде выполнимо, так что давайте произведем некоторые расчеты.

Прежде всего укажем все метрики шрифта как пользовательские свойства CSS, а затем вычислим font-size, при котором высота прописных букв будет равняться 100px.

p {
/* метрики шрифта */
—font: Catamaran;
—fm-capitalHeight: 0.68;
—fm-descender: 0.54;
—fm-ascender: 1.1;
—fm-linegap: 0;

/* необходимый размер шрифта для высоты прописных букв */
—capital-height: 100;

/* применить font-family */
font-family: var(—font);

/* рассчитать размер шрифта для получения высоты прописных букв, равной необходимому размеру шрифта */
—computedFontSize: (var(—capital-height) / var(—fm-capitalHeight));
font-size: calc(var(—computedFontSize) * 1px);
}

Довольно просто, не так ли? Но как быть, если нам нужно, чтобы текст был визуально по центру, а оставшееся пространство равномерно распределялось сверху и снизу от буквы «B»? Для этого необходимо рассчитать vertical-align на основании соотношения между верхним и нижним выносными элементами.

Сначала вычислим line-height: normal и высоту области содержимого:

p {

—lineheightNormal: (var(—fm-ascender) + var(—fm-descender) + var(—fm-linegap));
—contentArea: (var(—lineheightNormal) * var(—computedFontSize));
}

Затем нам потребуются:

  • расстояние от низа прописной буквы до нижнего края;
  • расстояние от верха прописной буквы до верхнего края.

Примерно так:

p {

—distanceBottom: (var(—fm-descender));
—distanceTop: (var(—fm-ascender) — var(—fm-capitalHeight));
}

Теперь можем вычислить vertical-align как разницу между этими расстояниями, умноженную на вычисленное значение font-size (Это значение нужно применить к строчному дочернему элементу).

p {

—valign: ((var(—distanceBottom) — var(—distanceTop)) * var(—computedFontSize));
}
span {
vertical-align: calc(var(—valign) * -1px);
}

И наконец, задаем необходимое значение line-height и вычисляем его, сохраняя вертикальное выравнивание:

p {

/* необходимая высота строки */
—line-height: 3;
line-height: calc(((var(—line-height) * var(—capital-height)) — var(—valign)) * 1px);
}

Теперь довольно просто добавить графический элемент той же высоты, что и буква «B»:

span::before {
content: »;
display: inline-block;
width: calc(1px * var(—capital-height));
height: calc(1px * var(—capital-height));
margin-right: 10px;
background: url(‘https://cdn.pbrd.co/images/yBAKn5bbv.png’);
background-size: cover;
}

Напоминаю, что этот тест показан исключительно для демонстрации, и полагаться на его результаты не стоит. Причин тут много:

  • Если метрики шрифта непостоянны, то расчеты в браузере постоянными не будут. ¯(ツ)/¯
  • Если шрифт не загрузился, то метрики резервного шрифта, по всей вероятности, будут другими, и работать со множеством значений быстро станет невозможно.

Подведем итоги

Рабочие примеры:

  • JSBin
  • gist

Что мы выяснили:

  • Строчный (inline) контекст форматирования действительно сложен для понимания.
  • У всех строчных элементов есть две высоты:
    • высота области содержимого (которая зависит от метрик шрифта);
    • высота виртуальной области (line-height);
    • ни одну из них совершенно точно нельзя визуализировать (разве что вы занимаетесь инструментальными средствами разработки и решили исправить этот недочет, — тогда было бы просто чудесно).

  • line-height: normal зависит от метрик шрифта.
  • из-за line-height: n виртуальная область может стать меньше области содержимого.
  • на vertical-align особо полагаться не стоит.
  • высота контейнера строки вычисляется при помощи свойств line-height и vertical-align его дочерних элементов.
  • Мы не можем просто получить или задать метрики шрифта через CSS.

Но я все равно люблю CSS 🙂

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

  • метрики шрифта: FontForge, opentype.js
  • вычислить line-height: normal и некоторые пропорции в браузере;
  • Ahem — специальный шрифт, чтобы понять, как это работает
  • более глубокое формальное объяснение строчного контекста форматирования
  • будущая спецификация по данной теме для помощи с вертикальным выравниванием: Line Grid module
  • метрики шрифта, API Уровень 1, сборник интересных идей (Гудини)

Источник