I want to change not the font-size of text, but two independent properties relative to its width and height.
So, by applying font-width: 50% to this element:
the text would be stretched to half:
Is this possible to do using CSS?
asked Oct 4, 2015 at 10:05
cabralpintocabralpinto
1,7443 gold badges13 silver badges29 bronze badges
4
CSS transform has the scale function for this:
p {
display: inline-block;
font-size: 32px;
transform: scale(.5, 1);
}
<p>This is text.</p>
Use the two numbers in the function for X- and Y-axis respectively.
answered Oct 4, 2015 at 10:14
Sebastian SimonSebastian Simon
17.7k7 gold badges55 silver badges73 bronze badges
0
You can try scaling the font in x direction.
p{
-webkit-transform: scaleX(0.5);
transform: scaleX(0.5);
}
answered Oct 4, 2015 at 10:17
AakashAakash
1,7411 gold badge14 silver badges21 bronze badges
The closest thing I can find is font-weight
It accepts not only bold,normal but also numeric values. 100-900 in 100 increments.
. Paragraph {font-weight :700;}
This combined with height properties should help but will not give you complete solution
Also look at spacing properties as you can reduce the the width of the words that way
letter-spacing: 2px;
answered Oct 4, 2015 at 10:23
2
Using a svg text with preserveAspectRatio="none" allow text deformations and very precise positioning.
To adjust, It’s all about the viewBox. The rendering stays natively responsive to browser resizes.
The text stays select able.
.title {
width: 540px;
height: 40px
}
.content {
width: 300px;
height: 400px
}
.side {
width: 270px;
height: 100px;
color: red;
position: absolute;
right: 30px;
top: 160px;
transform: rotate(44deg)
}
<div class="title">
<svg preserveAspectRatio="none" x="0" y="30" viewBox="0 0 100 15" width="100%" height="100%">
<foreignObject x="5" y="1" height="100%" width="100%">
<div>
Hello world!
</div>
</foreignObject>
</svg>
</div>
<div class="content">
<svg preserveAspectRatio="none" x="0" y="30" viewBox="0 0 400 200" width="100%" height="100%">
<foreignObject x="55" y="15" height="100%" width="80%">
<div>
The best way to use a hello cheer for introducing players is to have one cheerleader use a megaphone or loudspeaker to announce the players names and stats.
</div>
</foreignObject>
</svg>
</div>
<div class="side">
<svg preserveAspectRatio="none" x="0" y="30" viewBox="0 0 100 100" width="100%" height="100%">
<foreignObject x="5" y="15" height="200%" width="100%">
<div>
NOW WITH COLORS!
</div>
</foreignObject>
</svg>
</div>
Tip: For complex stuffs, flyers making, using the cm css unit works very well.
answered Sep 30, 2020 at 22:07
NVRMNVRM
10.6k1 gold badge82 silver badges85 bronze badges
3
Описание
CSS Свойство font-size определяет размер шрифта. Это свойство также используется для вычисления размера em, ex и других относительных единиц. Подробнее: <length>.
Интерактивный пример
Синтаксис
/* значения в <абсолютных размерах> */
font-size: xx-small;
font-size: x-small;
font-size: small;
font-size: medium;
font-size: large;
font-size: x-large;
font-size: xx-large;
/* значения в <относительных размерах> */
font-size: larger;
font-size: smaller;
/* <значения длины> */
font-size: 12px;
font-size: 0.8em;
/* <процентные значения> */
font-size: 80%;
/* Глобальные значения */
font-size: inherit;
font-size: initial;
font-size: unset;
Свойство font-size устанавливается одним из следующих способов:
- Ключевым словом из перечня абсолютных значений или относительных значений
- Как
<значение длины>или<процентное значение>, по отношению к размеру родительского элемента.
Значения
xx-small, x-small, small, medium, large, x-large, xx-large-
Набор ключевых слов абсолютных значений, по отношению к пользовательскому размеру шрифта по умолчанию (им считается
medium— среднее). larger, smaller-
Больше (larger) или меньше (smaller). Ключевые слова для относительного размера. Шрифт будет больше или меньше по отношению в размеру шрифта родительского элемента.Примерно на такое же соотношение, которое используется в ключевых словах абсолютного размера выше.
<length>-
Положительное значение длины
<length>. Для большинства единиц измерения, зависимых от шрифта (таких какemиex), размер шрифта будет зависеть от размера шрифта родительских элементов.Для единиц измерения, зависимых от шрифта, которые зависят от корневых единиц (таких какrem), размер шрифта будет коррелироваться по отношению к шрифту, используемому корневым элементом<html>(root). <процентные значения>-
Положительное процентное
<percentage>значение по отношению к размеру шрифта родительского элемента.
Примечание: Для обеспечения максимальной совместимости обычно лучше использовать значения, относящиеся к размеру шрифта пользователя по умолчанию.
Формальный синтаксис
Возможные подходы
Существуют разные способы задания размера шрифта. С помощью ключевых слов или с помощью числовых значений для размера пикселей или размера ems. Выберите подходящий метод в зависимости от потребностей конкретной веб-страницы.
Ключевые слова
Keywords are a good way to set the size of fonts on the web. By setting a keyword font size on the body element, you can set relative font-sizing everywhere else on the page, giving you the ability to easily scale the font up or down on the entire page accordingly.
Pixels
Setting the font size in pixel values (px) is a good choice when you need pixel accuracy. A px value is static. This is an OS-independent and cross-browser way of literally telling the browsers to render the letters at exactly the number of pixels in height that you specified. The results may vary slightly across browsers, as they may use different algorithms to achieve a similar effect.
Font sizing settings can also be used in combination. For example, if a parent element is set to 16px and its child element is set to larger, the child element displays larger than the parent element in the page.
Примечание: Defining font sizes in pixel is not accessible, because the user cannot change the font size from the browser. (For example, users with limited vision may wish to set the font size much larger than the size chosen by a web designer.) Therefore, avoid using pixels for font sizes if you wish to create an inclusive design.
Ems
Another way of setting the font size is with em values. The size of an em value is dynamic. When defining the font-size property, an em is equal to the size of the font that applies to the parent of the element in question. If you haven’t set the font size anywhere on the page, then it is the browser default, which is probably 16px. So, by default 1em = 16px, and 2em = 32px. If you set a font-size of 20px on the body element, then 1em = 20px and 2em = 40px. Note that the value 2 is essentially a multiplier of the current em size.
In order to calculate the em equivalent for any pixel value required, you can use this formula:
em = desired element pixel value / parent element font-size in pixels
For example, suppose the font-size of the body of the page is set to 1em, with the browser standard of 1em = 16px; if the font-size you want is 12px, then you should specify 0.75em (because 12/16 = 0.75). Similarly, if you want a font size of 10px, then specify 0.625em (10/16 = 0.625); for 22px, specify 1.375em (22/16).
A popular technique to use throughout the document is to set the the font-size of the body to 62.5% (that is 62.5% of the default of 16px), which equates to 10px, or 0.625em. Now you can set the font-size for any elements using em units, with an easy-to-remember conversion, by dividing the px value by 10. This way 6px = 0.6em, 8px = 0.8em, 12px = 1.2em, 14px = 1.4em, 16px = 1.6em. For example:
body {
font-size: 62.5%; /* font-size 1em = 10px on default browser settings */
}
span {
font-size: 1.6em; /* 1.6em = 16px */
}
The em is a very useful unit in CSS, since it automatically adapts its length relative to the font that the reader chooses to use.
One important fact to keep in mind: em values compound. Take the following HTML and apply it with the previous CSS above:
<div>
<span>Outer <span>inner</span> outer</span>
</div>
The result is:
Assuming that the browser’s default font-size is 16px, the words «outer» would be rendered at 16px, but the word «inner» would be rendered at 25.6px. This is because the inner span’s font-size is 1.6 em which is relative to its parent’s font-size, which is in turn relative to its parent’s font-size. This is often called compounding.
Rems
rem values were invented in order to sidestep the compounding problem. rem values are relative to the root html element, not the parent element. In other words, it lets you specify a font size in a relative fashion without being affected by the size of the parent, thereby eliminating compounding.
The CSS below is nearly identical to the previous example. The only exception is that the unit has been changed to rem.
html {
font-size: 62.5%; /* font-size 1em = 10px on default browser settings */
}
span {
font-size: 1.6rem;
}
Then we apply this CSS to the same HTML, which looks like this:
<span>Outer <span>inner</span> outer</span>
In this example, the words «outer inner outer» are all displayed at 16px (assuming that the browser’s font-size has been left at the default value of 16px).
Примеры
Пример 1
/* Set paragraph text to be very large. */
p { font-size: xx-large }
/* Set h1 (level 1 heading) text to be 2.5 times the size
* of the text around it. */
h1 { font-size: 250% }
/* Sets text enclosed within span tag to be 16px */
span { font-size: 16px; }
Пример 2
.small {
font-size: xx-small;
}
.larger {
font-size: larger;
}
.point {
font-size: 24pt;
}
.percent {
font-size: 200%;
}
<h1 class="small">Small H1</h1>
<h1 class="larger">Larger H1</h1>
<h1 class="point">24 point H1</h1>
<h1 class="percent">200% H1</h1>
Live Sample
Примечание
em and ex units on the font-size property are relative to the parent element’s font size (unlike all other properties, where they’re relative to the font size on the element). This means em units and percentages do the same thing for font-size.
Спецификации
| Specification |
|---|
| CSS Fonts Module Level 4 # font-size-prop |
Совместимость браузеров
BCD tables only load in the browser
Высота шрифта
Последнее обновление: 21.04.2016

Для установки размера шрифта используется свойство font-size:
div{
font-size: 18px;
}
В данном случае высота шрифта составит 18 пикселей. Пиксели представляют наиболее часто используемые единицы измерения. Чтобы задать значение в пикселях, после самого значения идет сокращение «px».
Если к тексту явным образом не применяется высота шрифта, то используются значения браузера по умолчанию. Например, для простого текста в параграфах
это 16 пикселей. Это базовый стиль текста.
Базовый стиль для разных элементов текста отличается: если для параграфов это 16 пикселей, то для заголовков h1 это 32 пикселя, для заголовков h2 — 24 пикселя и т..д.
Для измерения шрифта также можно использовать самые разные единицы измерения.
Ключевые слова
В CSS имеется семь ключевых слов, которые позволяют назначить размер шрифта относительно базового:
-
medium: базовый размер шрифта браузера (16 пикселей)
-
small: 13 пикселей
-
x-small: 10 пикселей
-
xx-small: 9 пикселей
-
large: 18 пикселей
-
x-large: 24 пикселя
-
xx-large: 32 пикселя
Например:
font-size: x-large;
Проценты
Проценты позволяют задать значение относительно базового или унаследованного шрифта. Например:
font-size: 150%;
В данном случае высота шрифта будет составлять 150% от базового, то есть 16px * 1,5 = 24px
Наследование шрифта может изменить финальное значение. Например, следующую ситуацию:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Шрифты в CSS3</title>
<style>
div {font-size: 10px;}
p {font-size: 150%;}
</style>
</head>
<body>
<div>
<p>Однажды в студеную зимнюю пору</p>
</div>
</body>
</html>
Здесь элемент p наследует от контейнера — блока div шрифт высотой в 10 пикселей. То есть 10 пикселей теперь будет базовым для параграфа.
Далее для элемента p определяется новая высота шрифта в 150%. Это значит, что финальная высота будет равна 10px * 1,5 = 15px.
Единица еm
Единица измерения еm во многом эквивалентна процентам. Так, 1em равен 100%, .5em равно 50% и т.д.
| Internet Explorer | Chrome | Opera | Safari | Firefox | Android | iOS | |
| 6.0+ | 8.0+ | 1.0+ | 3.5+ | 1.0+ | 1.0+ | 1.0+ | 1.0+ |
Краткая информация
| Значение по умолчанию | medium |
|---|---|
| Наследуется | Да |
| Применяется | Ко всем элементам |
| Ссылка на спецификацию | http://www.w3.org/TR/CSS21/fonts.html#propdef-font-size |
Версии CSS
| CSS 1 | CSS 2 | CSS 2.1 | CSS 3 |
|---|---|---|---|
Описание
Определяет размер шрифта элемента. Размер может быть установлен несколькими
способами. Набор констант (xx-small, x-small, small,
medium, large, x-large, xx-large) задает размер, который называется абсолютным.
По правде говоря, они не совсем абсолютны, поскольку зависят от настроек браузера
и операционной системы.
Другой набор констант (larger, smaller)
устанавливает относительные размеры шрифта. Поскольку размер унаследован от
родительского элемента, эти относительные размеры применяются к родительскому
элементу, чтобы определить размер шрифта текущего элемента.
В конечном итоге, размер шрифта сильно зависит от значения свойства font-size у родителя элемента.
Сам размер шрифта определяется как высота от базовой линии до верхней границы кегельной площадки, как показано на рис. 1.
Рис. 1. Размер шрифта
Синтаксис
font-size: абсолютный размер | относительный размер | значение | проценты | inherit
Значения
Для задания абсолютного размера используются следующие значения: xx-small,
x-small, small, medium,
large, x-large, xx-large.
Их соответствие с размером шрифта в HTML приведено в табл. 1.
| CSS | xx-small | x-small | small | medium | large | x-large | xx-large | |
|---|---|---|---|---|---|---|---|---|
| HTML | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Относительный размер шрифта задается значениями larger и smaller.
Также разрешается использовать любые допустимые единицы CSS: em
(высота шрифта элемента), ex (высота символа х),
пункты (pt), пикселы (px),
проценты (%) и др. За 100% берется размер шрифта
родительского элемента. Отрицательные значения не допускаются.
- inherit
- Наследует значение родителя.
Пример
HTML5CSS2.1IECrOpSaFx
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>font-size</title>
<style>
h1 {
font-family: 'Times New Roman', Times, serif; /* Гарнитура текста */
font-size: 250%; /* Размер шрифта в процентах */
}
p {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 11pt; /* Размер шрифта в пунктах */
}
</style>
</head>
<body>
<h1>Duis te feugifacilisi</h1>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diem
nonummy nibh euismod tincidunt ut lacreet dolore magna aliguam erat volutpat.
Ut wisis enim ad minim veniam, quis nostrud exerci tution ullamcorper suscipit
lobortis nisl ut aliquip ex ea commodo consequat.</p>
</body>
</html>
Результат данного примера показан на рис. 1.
Рис. 2. Применение свойства font-size
Объектная модель
[window.]document.getElementById(«elementID«).style.fontSize
Браузеры
Internet Explorer до версии 7.0 включительно не поддерживает значение inherit.
Серёжа СыроежкинКопирайтер
Размер шрифта на сайте можно задать как при помощи HTML, так и с помощью CSS. Рассмотрим оба варианта.
Задание размера шрифта с помощью HTML
Размер шрифта на странице можно определить при помощи тега font HTML. В статье Цвет шрифта HTML мы уже рассматривали тег font и его атрибуты. Одним из атрибутов этого тега является size, который и позволяет установить размер шрифта. Применяется он следующим образом:
Конструктор сайтов <font size="7">"Нубекс"</font>
Size может принимать значения от 1 до 7 (по умолчанию равен 3, что соответствует 13,5 пунктам для шрифта Times New Roman). Другой вариант задания атрибута – “+1” или “-1”. Это означает, что размер будет изменен относительно базового на 1 пункт больше или меньше, соответственно.
Приведенный способ довольно прост в использовании и незаменим при необходимости изменения размера шрифта небольшого куска текста. В остальных случаях рекомендуется определять стиль текста с помощью CSS.
Устанавливаем размер шрифта при помощи CSS
В CSS для изменения размера шрифта применяется свойство font-size, которое применяется следующим образом:
<html>
<head>
<title>Меняем размер шрифта при помощи CSS</title>
<style>
.nubex {
font-size: 14px;
}
</style>
</head>
<body>
<div class="nubex">Шрифты HTML-блока div класса nubex получают размер 14px при помощи свойства font size.</div>
</body>
</html>
В приведенном примере размер шрифта устанавливается в пикселях. Но существуют и другие способы задания размера:
- large, small, medium — задают абсолютный размер (маленький, средний, большой). Также могут применяться значения экстра-маленький (x-small, xx-small), экстра-большой (x-large, xx-large).
- larger, smaller — задают относительный размер (меньше или больше относительно родительского элемента).
- 100% — задается относительный размер (в процентах относительно родительского). Например:
h1 { font-size: 180%; }Это означает, что размер тега H1 будет составлять 180% от базового размера шрифта.
- Другие варианты задания относительного размера:
- 5ex — означает, что размер составит 5 высот буквы x от базового шрифта;
- 14pt — 14 пунктов;
- 22px — 22 пикселя;
- 1vw — 1% от ширины окна браузера;
- 1vh — 1% от высоты окна браузера;
Смотрите также:
Перевод статьи Deep dive CSS: font metrics, line-height and vertical-align с сайта iamvdo.me, опубликовано на css-live.ru с разрешения автора — Венсана де Оливейры.
Line-height и vertical-align — простые CSS-свойства. Настолько простые, что большинство из нас уверены, что понимают, как они работают и как ими пользоваться. Но это не так. На деле они сложны, может быть, сложнее всех, потому что у них ведущая роль в создании одной из самых малоизвестных особенностей CSS: строчного (инлайнового) контекста форматирования.
Например, line-height можно задать в виде длины или безразмерного значения 1, но по умолчанию у него значение 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> с 3 <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, разная высота в итоге
Даже если мы в курсе этой особенности, почему font-size: 100px не делает элементы высотой 100px? Я измерил эти значения: Helvetica — 115px, Gruppo — 97px и Catamaran — 164px.
Высота элементов с font-size: 100px колеблется от 97px до 164px
Хотя на первый взгляд это странно, это вполне ожидаемо. Причина в самом шрифте. Вот как это работает:
- шрифт задает свои единицы измерения em-квадрата (или UPM, units per em — единиц на кегль), некий контейнер, в котором будут рисоваться все символы. В этом контейнере всё измеряется в относительных единицах и обычно он принимается за 1000 единиц. Но бывает и 1024, и 2048, и сколько угодно.
- на базе этих относительных единиц задаются метрики шрифта: высота верхних выносных элементов (ascender), нижних выносных (descender), заглавных букв (capital height), строчных букв (x-height) и т.п. Заметьте, что некоторые значения могут выступать за рамки em-квадрата.
- в браузере эти относительные единицы масштабируются до заданного font-size.
Возьмем шрифт Catamaran и откроем его в FontForge, чтобы увидеть метрики:
- em-квадрат принят за 1000 единиц
- высота верхних выносных — 1100, а нижних — 540. Судя по нескольким тестам, браузеры используют значения HHead Ascent/Descent на Mac OS и Win Ascent/Descent на Windows (и эти значения могут различаться!). Также видно, что высота заглавных букв (Capital Height) равна 680, а высота строчных (X height) — 485.
Значения метрик шрифта в FontForge
Это значит, что шрифт Catamaran использует 1100 + 540 единиц из em-квадрата в 1000 единиц, что при font-size: 100px дает высоту 164px. Эта вычисленная высота определяет область содержимого элемента, так я и буду называть ее всю статью. Можете представлять область содержимого как ту область, к которой применяется свойство background 2.
Также легко предсказать, что высота заглавных букв будет 68px (680 единиц), а строчных (x-высота) — 49px (485 единиц). Как результат, 1ex = 49px, а 1em = 100px, а не 164px (к счастью, em отсчитывается от font-size, а не от вычисленной высоты)
Шрифт Catamaran: единицы на em (UPM) и их эквиваленты в пикселях при font-size: 100px
Прежде чем углубляться дальше, вкратце рассмотрим основные понятия, с которыми предстоит иметь дело. Когда элемент <p> отображается на экране, он может состоять из нескольких строк, в зависимости от ширины. Каждая строка набирается из нескольких элементов строки (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 контейнера строки:
- в первом и последнем — только по одному анонимному элементу строки (текст)
- во втором — два анонимных элемента строки и 3
<span>-а
Элемент <p> (черная рамка) состоит из контейнеров строк (белые рамки), состоящих из строчных элементов (сплошные рамки) и анонимных элементов строки (пунктирные рамки)
Хорошо видно, что второй контейнер строки выше остальных, из-за вычисленной области содержимого его потомков, а точнее — того, что со шрифтом Catamaran.
Самое сложное в создании контейнера строки то, что мы не можем ни толком это увидеть, ни управлять этим из CSS. Даже задание фона для ::first-line не помогает представить высоту первого контейнера строки наглядно.
До сих пор я ввел два понятия: область содержимого и контейнер строки. Если вы читали внимательно, я сказал, что высота контейнера строки рассчитывается по высоте его потомков, я не говорил «высоте области содержимого потомков». И в этом большая разница.
Хоть это может прозвучать странно, у элемента строки есть две разных высоты: высота области содержимого и высота виртуальной области (я придумал термин «виртуальная область», потому что эта высота нам не видна, но в спецификации вы нигде этого термина не найдете).
- высота области содержимого определяется метриками шрифта (как мы видели раньше)
- высота виртуальной области — это
line-height, и именно эта высота используется при расчете высоты контейнера строки
У элементов строки есть две разные высоты
Помимо прочего, это опровергает популярное представление, что line-height — это расстояние между базовыми линиями шрифта. В CSS это не так 3.
В CSS line-height — не расстояние между базовыми линиями
Вычисленная разность высот между виртуальной областью и областью содержимого называется «leading», или интерлиньяж (прим. перев.: в некоторых русскоязычных источниках «интерлиньяжем» называют саму «высоту виртуальной области» в терминах Венсана, что часто приводит к путанице. Интересно, что во французской версии статьи Венсан использует тоже англоязычный термин «leading»). Половина интерлиньяжа добавляется сверху от области содержимого, вторая половина снизу от нее. Таким образом, область содержимого всегда будет посередине виртуальной области.
В зависимости от вычисленного значения, line-height (виртуальная область) может быть равна, выше или ниже области содержимого. Если виртуальная область ниже, то интерлиньяж отрицательный и контейнер строки визуально оказывается ниже собственных потомков.
Есть и другие виды элементов строки:
- замещаемые элементы строки (
<img>,<input>,<svg>и т.п.) - элементы типа
inline-blockи прочихinline-* - строчные элементы, участвующие в особых контекстах форматирования (например, во флекс-контейнере все флекс-элементы «блокифицируются»)
Для этих особых строчных элементов высота рассчитывается по их свойствам height, margin and border. Если у height значение auto, то используется line-height, и высота области содержимого строго равна line-height.
У замещаемых строчных элементов, элементов типа inline-block/inline-* и «блокифицированных» строчных элементов высота области содержимого равна их высоте, или 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 (2288/2048≈1,117), а line-height: normal — 115 px (2355/2048≈1.15). Все эти метрики специфичны для каждого шрифта и заданы дизайнером-шрифтовиком, который его создал.
Становится очевидно, что указывать line-height: 1 — плохой подход. Напоминаю, что безразмерные значения отсчитываются от font-size, а не от области содержимого, и немало проблем возникает от того, что виртуальная область оказывается меньше области содержимого.
Из-за line-height: 1 контейнер строки может стать ниже, чем область содержимого
Но не только line-height: 1. Например, из 1117 шрифтов, установленных на моем компьютере (да, я установил все шрифты из Google Web Fonts) у 1059, это около 95%, вычисленная line-height больше 1. Вообще вычисленная line-height у них колеблется от 0.618 до 3.378. Вам не померещилось, 3.378!
Немного подробностей о расчете контейнера строки:
- для строчных элементов
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 «выравнивает вертикальную середину бокса с базовой линией родительского бокса плюс половина родительской x-высоты». Положение базовых линий бывает разное, x-высота — тоже, так что и на middle положиться нельзя. Хуже всего то, что в большинстве сценариев middle никогда не бывает по-настоящему «посередине». Слишком много всего влияет и это нельзя прописать в CSS (x-высота, относительное положение базовой линии и т.п.)
Отмечу, что есть еще 4 значения, полезные в некоторых случаях:
vertical-align: top/bottomвыравнивают по верху или низу контейнера строкиvertical-align: text-top/text-bottomвыравнивают по верху или низу области содержимого
Vertical-align: top, bottom, text-top и text-bottom
Но будьте осторожны: во всех случаях оно выравнивает виртуальную область, высота которой невидима. Взгляните на этот простой пример с vertical-align: top. Невидимая line-height может давать странные, хотя и предсказуемые, результаты.
vertical-align может давать на первый взгляд странный результат, хотя, если наглядно представить line-height, всё ожидаемо
Наконец, vertical-align принимает также числовые значения, которые поднимают или опускают бокс относительно базовой линии. Этот последний вариант часто может выручить.
«CSS is awesome»
Мы поговорили о взаимодействии line-height и vertical-align, но вопрос-то вот в чем: можно ли управлять метриками шрифта из CSS? Короткий ответ: нет. Хотя я очень на это надеялся. Как бы то ни было, думаю, пора нам немного поразмяться. Метрики шрифтов — константы, что-то же у нас в любом случае получится.
Что если, например, нам нужен текст шрифтом Catamaran, в котором заглавные буквы будут ровно 100px высотой? С виду осуществимо: давайте немного посчитаем.
Первым делом укажем все метрики шрифта в виде пользовательских свойств CSS 4, затем рассчитаем, при каком font-size заглавные буквы будут высотой 100px.
p {
/* метрики шрифта */
--font: Catamaran;
--capitalHeight: 0.68;
--descender: 0.54;
--ascender: 1.1;
--linegap: 0;
/* нужная высота заглавных букв */
--fontSize: 100;
/* apply font-family */
font-family: var(--font);
/* рассчитываем font-size для получения нужной высоты заглавных букв */
--computedFontSize: (var(--fontSize) / var(--capitalHeight));
font-size: calc(var(--computedFontSize) * 1px);
}
Теперь заглавные буквы высотой 100px
Достаточно очевидно, правда? Но что если мы хотим вертикально отцентрировать текст, чтобы свободное место поровну распределялось сверху и снизу от буквы «B»? Чтобы добиться этого, придется рассчитать vertical-align на основе положения базовой линии (пропорции верхней/нижней частей).
Сначала рассчитаем величину line-height: normal и высоту области содержимого:
p {
…
--lineheightNormal: (var(--ascender) + var(--descender) + var(--linegap));
--contentArea: (var(--lineheightNormal) * var(--computedFontSize));
}
Затем нам понадобятся:
- расстояние от низа заглавной буквы до нижнего края
- расстояние от верха заглавной буквы до верхнего края
Примерно так:
p {
…
--distanceBottom: (var(--descender));
--distanceTop: (var(--ascender) - var(--capitalHeight));
}
Теперь можно рассчитать значение vertical-align, которое будет равно разнице этих расстояний, умноженной на вычисленное значение font-size (нам надо будет применить это значение к строчному дочернему элементу).
p {
…
--valign: ((var(--distanceBottom) - var(--distanceTop)) * var(--computedFontSize));
}
span {
vertical-align: calc(var(--valign) * -1px);
}
И в конце зададим желаемую высоту строки и вычислим соответствующий line-height так, чтобы вертикальное выравнивание сохранилось:
p {
…
/* желаемая высота строки */
--lineheight: 3;
line-height: calc(((var(--lineheight) * var(--fontSize)) - var(--valign)) * 1px);
}
Результаты для разных line-height. Текст всегда посередине.
Теперь легко добавить иконку одной высоты с буквой «B»:
span::before {
content: '';
display: inline-block;
width: calc(1px * var(--fontSize));
height: calc(1px * var(--fontSize));
margin-right: 10px;
background: url('https://cdn.pbrd.co/images/yBAKn5bbv.png');
background-size: cover;
}
Иконка и буква «B» равны по высоте
Посмотреть результат в JSBin
Учтите, что этот тест только для демонстрационных целей. Полагаться на это нельзя. Причин много:
- метрики шрифтов-то постоянны, но вот браузерные вычисления — не очень ¯(ツ)/¯
- если шрифт не загрузился, у резервного шрифта скорее всего другие метрики, а работать с несколькими разными значениями быстро станет практически нереально.
В сухом остатке
Что мы узнали:
- понять строчный (инлайновый) контекст форматирования нелегко
- у всех строчных элементов 2 высоты
- область содержимого (основанная на метриках шрифта)
- виртуальная область (
line-height) - ни ту, ни другую высоту нельзя однозначно визуализировать (если вы разрабатываете браузерный отладчик и готовы взяться за это — было бы великолепно!)
line-height: normalосновывается на метриках шрифта- при
line-height: nвиртуальная область может стать меньше, чем область содержимого - на
vertical-alignнельзя особо полагаться - высота контейнера строки рассчитывается на основе свойств
line-heightиvertical-alignего потомков - нельзя просто взять и получить/установить метрики шрифта из CSS
- есть в планах спецификация на эту тему, чтобы помочь с вертикальным выравниванием: модуль строчной сетки (Line Grid)
Но я по-прежнему люблю CSS 
Полезные ссылки
- Получить метрики шрифта: FontForge, opentype.js
- Рассчитать
line-height: normalи некоторые пропорции в браузере - Ahem, специальный шрифт, чтобы легче разобраться, как это работает
- Еще более глубокое и основательное разъяснение строчного контекста форматирования
- неважно, что вы выберете, здесь речь не об этом ↩
- это не совсем так ↩
- в других редакторах это может быть и расстояние между базовыми линиями. В Ворде, в Фотошопе это так. Главное отличие в том, что в CSS оно влияет и на первую строку ↩
- можно использовать и переменные из препроцессоров, не в пользовательских свойствах суть ↩
P.S. Это тоже может быть интересно:




















