Единицы измерения: px, em, rem и другие
В этом очерке я постараюсь не только рассказать о различных единицах измерения, но и построить общую картину – что и когда выбирать.
Пиксели: px
Пиксель px – это самая базовая, абсолютная и окончательная единица измерения.
Количество пикселей задаётся в настройках разрешения экрана, один px – это как раз один такой пиксель на экране. Все значения браузер в итоге пересчитает в пиксели.
Пиксели могут быть дробными, например размер можно задать в 16.5px . Это совершенно нормально, браузер сам использует дробные пиксели для внутренних вычислений. К примеру, есть элемент шириной в 100px , его нужно разделить на три части – волей-неволей появляются 33.333. px . При окончательном отображении дробные пиксели, конечно же, округляются и становятся целыми.
Для мобильных устройств, у которых много пикселей на экране, но сам экран маленький, чтобы обеспечить читаемость, браузер автоматически применяет масштабирование.
- Главное достоинство пикселя – чёткость и понятность
- Другие единицы измерения – в некотором смысле «мощнее», они являются относительными и позволяют устанавливать соотношения между различными размерами
Существуют также «производные» от пикселя единицы измерения: mm , cm , pt и pc , но они давно отправились на свалку истории.
Вот, если интересно, их значения:
- 1mm (мм) = 3.8px
- 1cm (см) = 38px
- 1pt (типографский пункт) = 4/3 px
- 1pc (типографская пика) = 16px
Так как браузер пересчитывает эти значения в пиксели, то смысла в их употреблении нет.
В реальной жизни сантиметр – это эталон длины, одна сотая метра. А пиксель может быть разным, в зависимости от экрана.
Но в формулах выше под пикселем понимается «сферический пиксель в вакууме», точка на «стандартизованном экране», характеристики которого описаны в спецификации.
Поэтому ни о каком соответствии cm реальному сантиметру здесь нет и речи. Это полностью синтетическая и производная единица измерения, которая не нужна.
Относительно шрифта: em
1em – текущий размер шрифта.
Можно брать любые пропорции от текущего шрифта: 2em , 0.5em и т.п.
Размеры в em – относительные, они определяются по текущему контексту.
Например, давайте сравним px с em на таком примере:
24 пикселей – и в Африке 24 пикселей, поэтому размер шрифта в <div> одинаков.
А вот аналогичный пример с em вместо px :
Так как значение в em высчитывается относительно текущего шрифта, то вложенная строка в 1.5 раза больше, чем первая.
Выходит, размеры, заданные в em , будут уменьшаться или увеличиваться вместе со шрифтом. С учётом того, что размер шрифта обычно определяется в родителе, и может быть изменён ровно в одном месте, это бывает очень удобно.
Что такое «размер шрифта»? Это вовсе не «размер самой большой буквы в нём», как можно было бы подумать.
Размер шрифта – это некоторая «условная единица», которая встроена в шрифт.
Она обычно чуть больше, чем расстояние от верха самой большой буквы до низа самой маленькой. То есть, предполагается, что в эту высоту помещается любая буква или их сочетание. Но при этом «хвосты» букв, таких как р , g могут заходить за это значение, то есть вылезать снизу. Поэтому обычно высоту строки делают чуть больше, чем размер шрифта.
В спецификации указаны также единицы ex и ch, которые означают размер символа "x" и размер символа "0" .
Эти размеры присутствуют в шрифте всегда, даже если по коду этих символов в шрифте находятся другие значения, а не именно буква "x" и ноль "0" . В этом случае они носят более условный характер.
Эти единицы используются чрезвычайно редко, так как «размер шрифта» em обычно вполне подходит.
Проценты %
Проценты % , как и em – относительные единицы.
Когда мы говорим «процент», то возникает вопрос – «Процент от чего?»
Как правило, процент будет от значения свойства родителя с тем же названием, но не всегда.
Это очень важная особенность процентов, про которую, увы, часто забывают.
Отличный источник информации по этой теме – стандарт, Visual formatting model details.
Вот пример с % , он выглядит в точности так же, как с em :
В примере выше процент берётся от размера шрифта родителя.
А вот примеры-исключения, в которых % берётся не так:
margin-left При установке свойства margin-left в % , процент берётся от ширины родительского блока, а вовсе не от его margin-left . line-height При установке свойства line-height в % , процент берётся от текущего размера шрифта, а вовсе не от line-height родителя. Детали по line-height и размеру шрифта вы также можете найти в статье Свойства font-size и line-height. width/height Для width/height обычно процент от ширины/высоты родителя, но при position:fixed , процент берётся от ширины/высоты окна (а не родителя и не документа). Кроме того, иногда % требует соблюдения дополнительных условий, за примером – обратитесь к главе Особенности свойства height в %.
Единица rem: смесь px и em
Итак, мы рассмотрели:
- px – абсолютные, чёткие, понятные, не зависящие ни от чего.
- em – относительно размера шрифта.
- % – относительно такого же свойства родителя (а может и не родителя, а может и не такого же – см. примеры выше).
Может быть, пора уже остановиться, может этого достаточно?
Э-э, нет! Не все вещи делаются удобно.
Вернёмся к теме шрифтов. Бывают задачи, когда мы хотим сделать на странице большие кнопки «Шрифт больше» и «Шрифт меньше». При нажатии на них будет срабатывать JavaScript, который будет увеличивать или уменьшать шрифт.
Вообще-то это можно сделать без JavaScript, в браузере обычно есть горячие клавиши для масштабирования вроде Ctrl + + , но они работают слишком тупо – берут и увеличивают всю страницу, вместе с изображениями и другими элементами, которые масштабировать как раз не надо. А если надо увеличить только шрифт, потому что посетитель хочет комфортнее читать?
Какую единицу использовать для задания шрифтов? Наверно не px , ведь значения в px абсолютны, если менять, то во всех стилевых правилах. Вполне возможна ситуация, когда мы в одном правиле размер поменяли, а другое забыли.
Следующие кандидаты – em и % .
Разницы между ними здесь нет, так как при задании font-size в процентах, эти проценты берутся от font-size родителя, то есть ведут себя так же, как и em .
Единицы размеров в CSS
В CSS существует множество единиц измерения. Обычно мы используем единицы размеров, но также есть единицы для углов — например, deg и turn , единицы времени — s и ms , единицы плотности экрана — например, dpi и dppx и другие.
Здесь будут рассматриваться только единицы размеров, которыми мы пользуемся чаще всего. Подробное описание можно найти в спецификации W3C Distance Units: the <length> type.
Общим для всех единиц длины будет то, что для значения 0 , единицы можно не указывать: height: 0px и height: 0 будут работать одинаково, так что единицы измерения можно отбросить. Это позволяет немного быстрее писать код и считывать значения свойств.
Абсолютные единицы измерения
| cm | сантиметр | 1cm = 96px/2.54 ≈ 37,795px |
| mm | миллиметр | 1mm = 1/10 от 1cm |
| q | четверь миллиметра | 1q = 1/40 от 1cm = 0.25mm ≈ 0.945px |
| in | дюйм | 1in = 2.54cm = 96px |
| pc | пика | 1pc = 1/6 от 1in |
| pt | пункт, точка | 1pt = 1/72 от 1in |
| px | пиксель | 1px = 1/96 от 1in, 0.75 от pt |
Абсолютные единицы относительны друг для друга (соотношения в последней колонке), но все они привязаны к конкретным величинам.
Для печатных устройств сантиметры, миллиметры и дюймы должны быть равны своим обычным значениям, но для экранов это будет не так:
Я попыталась разными способами получить полоску длиной 10 сантиметров. Все полоски равны друг другу, но ни одна не равна 10 сантиметрам, если приложить линейку к экрану. Проверила на двух мониторах: на одном они короче, на другом — длиннее.
На веб-страницах физические единицы измерения вроде cm , mm и in не будут работать как ожидается, потому что главная экранная единица измерения — пиксель.
Что такое пиксель и какого он размера? Чем отличаются пиксели px от точек pt ? Почему у них такие странные размеры в 1/96 дюйма и 1/72 дюйма соответственно? Как были выбраны эти значения и почему этих единиц измерения две? Попытка разобраться с мелкой точкой на экране вызывает множество вопросов и требует погружения в историю. Я попыталась выяснить как всё было, и вот что узнала.

Когда появились первые программы для предпечатной подготовки, нужно было как-то соотнести размер элементов на экране с тем, чтоб будет напечатано на бумаге. Тогда оказалось, что один дюйм (inch) на экране соответствует 72 точкам. Это соотношение зафиксировано в pt , pt — это 1/72 дюйма. Изначально это была типографская единица измерения, и её значения менялись со временем, но с появлением компьютерных программ для полиграфии значение pt пришлось стандартизировать.
С развитием технологий стало возможно делать экраны с большим разрешением, и Microsoft предложила отображать 96 точек на дюйм, что было зафиксировано в px , то есть пиксель — это 1/96 дюйма. Это позволило увеличить чёткость мелкого текста, потому что для отображения символа теперь можно было использовать больше точек.
Размер px составляет 0.75 от pt . По сути, pt — это более крупный пиксель.
Позже появились ретиновые дисплеи с повышенной плотностью пикселей, и тогда CSS-пиксели, которые мы используем, перестали соответствовать физическим пикселям экрана, теперь это виртуальная единица, размер которой определяется устройством вывода. Для нас это не играет особой роли кроме как при работе с изображениями, когда для ретины нужно подготовить дополнительный набор картинок. Все размеры, заданные в пикселях, будут корректно отображены на экране вне зависимости от того, сколько физических пикселей для этого потребуется.
На сегодняшний момент соотношение физических единиц к точкам экрана утратило прежний смысл, но осталось зафиксированым в спецификации для сохранения обратной совместимости и упрощения конвертации одних единиц в другие.
При этом важно помнить, что раз CSS-пиксели уже не соответствуют физическим точкам экрана, сантиметры и дюймы при выводе на экран тоже не будут не соответствовать своим реальным размерам, об этом есть и в спецификации:
If the anchor unit is the pixel unit, the physical units might not match their physical measurements. Alternatively if the anchor unit is a physical unit, the pixel unit might not map to a whole number of device pixels.
То есть, если использовать дюймы для вёрстки веб-страниц, один дюйм всегда будет равен 96 пикселям, но никогда — реальной физической единице:
Таким образом, главное в абсолютных единицах — контекст использования:
- для вывода на печать экранные пиксели должны быть приведены к физическими единицами, следовательно, для подготовки документов к печати лучше использовать их;
- для вывода на экран дюймы и сантиметры должны быть приведены к пикселям, следовательно, для веб-разработки лучше сразу использовать пиксели.
Пока копалась в истории единиц измерения, выяснилось, что во внутреннем коде Gecko когда-то была поддержка километров, удалили в 2009-м:

Из физических единиц ещё может представлять интерес q : это относительно новая единица, и она поддерживается не всеми браузерами. q — это 0.25mm . Как и другие физические единицы, больше имеет смысл для печати, но также можно попытаться использовать её для уменьшения размера кода: q — это примерно 0.945px , то есть в некоторых случаях вполне можно использовать её вместо пикселей, получается один символ ( q ) вместо двух ( px ).
Пример такого использования я подсмотрела в этом демо. Открывайте осторожно, может повиснуть браузер. Попытка посмотреть стили в веб-инспекторе вешает его почти гарантированно, поэтому лучше посмотрите исходный код страницы. Скриншот:

Чистое безумие, конечно. Картина воспроизведена с помощью box-shadow , и мне кажется, тему рисования на CSS на этом можно закрывать.
Вес стилей демо — 4.5Mb, а если бы там вместо q были пиксели, стили весили бы на 300Kb больше.
Относительные единицы измерения
Относительные единицы измерения вычисляются на основе каких-то других величин: размера шрифта или размера экрана, и могут динамически меняться вместе с ними.
Единицы измерения, привязанные к шрифту
| em | размер шрифта элемента |
| ex | высота x в нижнем регистре |
| ch | ширина 0 (ZERO, U+0030) |
| rem | размер шрифта корневого элемента |
Для font-size это унаследованный размер шрифта, для остальных свойств — текущий размер шрифта, уже вычисленный для font-size .
Чтобы увидеть это вживую, возьмем такой код:
Получилось вот что:
Розовая полоса — градиент высотой 1em , чтобы было с чем сравнивать.
Оба блока имеют одинаковый размер шрифта, уменьшенный относительно родительского элемента в два раза ( font-size: .5em; ). И как теперь указать толщину рамки равной размеру шрифта?
border-width: .5em делает рамку в два раза тоньше, чем нужно. Это происходит потому, что родительский размер шрифта использует только font-size , а border получает вычисленное значение из font-size .
Таким образом, если где-то не в font-size нужно использовать текущий размер шрифта, не нужно копировать значение размера, достаточно указать 1em . У правого блока рамка правильной толщины.
Ещё одно демо, для понимания как соотносятся em и символы шрифта. Цветные полосы имеют высоту 1em , поэтому видно, что 1em примерно соответствует высоте символов с учётом заглавных букв и выносных элементов:
Размер em нигде не зафиксирован, и вычисляется в момент использования на основе размера шрифта родителя. Например, если задать размер шрифта вот таким образом:
а потом вложить несколько дивов один в другой, размер шрифта каждого следующего дива будет меньше предыдущего:
Потому что 1em — это текущий унаследованный размер шрифта, а .75em — унаследованный шрифт, уменьшенный на четверть. Для каждого нового вложенного дива сначала наследуется уменьшенный шрифт родителя, а потом тоже уменьшается заданным образом.
Об этом нужно помнить, если вы захотите задавать в em размеры переиспользуемых компонентов: при вкладывании элементов друг в друга вычисленное значение em может оказаться не тем, что хотелось бы получить.
ex — это высота буквы x в нижнем регистре. Если в шрифте нет подходящей метрики, и в нём нет такого символа, браузер попробует вычислить ex самостоятельно. Если это по каким-то причинам невозможно, ex считается равным .5em .
В демо цветные полосы имеют высоту 1ex , и для выбранных шрифтов 1ex будет равен высоте маленькой x :
Посмотрим, как на ex влияет шрифт, и как ex соотносится с em .
В этом демо квадратикам в левой группе заданы размеры в 1em , в правой — в 2ex , так можно проверить равен ли ex половине em . Также каждому квадратику задан свой шрифт:
В отличие от em , размер ex будет меняться вместе со шрифтом, и во всех случаях 2ex не равно 1em , то есть на соотношение в .5 полагаться нельзя.
ex точно также как и em наследует размер шрифта родителя:
ch — ширина символа 0 . Для моноширинных шрифтов это точная ширина любого символа, для остальных — примерная ширина одного узкого символа. Если по каким-то причинам ширину невозможно вычислить, запасным значением будет .5em .
Эрик Мейер предостерегает от попыток использовать ch для задания ширины контейнера в символах, потому что это не работает как ожидается. В демо ниже ширина каждого блока с текстом задана вот таким образом:
Ширина блока будет верной только для моноширинных шрифтов (см. Courier ), в некоторых шрифтах будет работать и для цифр ( Arial , Comic Sans ), в остальных случаях нельзя рассчитывать, что 1ch будет равен ширине символа:
Сопоставим 1em , 2ex и 2ch :
- 1ch больше 1ex (ширина 0 больше высоты x );
- 1ch не равен половине em ;
- значение ch может меняться вместе со шрифтом.
rem — это root em , размер шрифта корневого элемента, для веб-страницы это элемент html . Размер шрифта по умолчанию — 16px . Это значение не зафиксировано в спецификации, но используется всеми браузерами. Про историю вопроса можно почитать в рассылке W3C.
Если пользователь в настройках браузера задаст другое значение, оно переопределит размер шрифта корневого элемента. То есть если нужно сделать интерфейс, который будет масштабироваться под размер шрифта, выбранный пользователем, в качестве единицы измерения удобно использовать именно rem .
Важно понимать, что размер rem можно переопределить только для элемента html . Например, возьмем такие стили:
Если rem можно было бы переопределять в любом месте, текст бы увеличился, но этого не произошло:
Высота цветной полосы 24px , чтобы было с чем сравнивать.
Если переопределить размер шрифта для элемента html , всё сработает:
В отличие от em , rem всегда содержит размер шрифта только корневого элемента, поэтому вложенность ни на что не влияет:
Это позволяет делать компоненты, размеры которых привязаны к базовому размеру шрифта, но не зависят от вложенности элементов друг в друга.
Единицы измерения, привязанные к размерам экрана
| vw | 1% ширины вьюпорта |
| vh | 1% высоты вьюпорта |
| vmin | 1% от меньшего из vw и vh |
| vmax | 1% от большего из vw и vh |
Эти единицы предназначены для создания элементов, размер которых должен зависеть от размера окна (вьюпорта).
100vh — это высота вьюпорта, очень удобно для элементов, которые должны растягиваться на всю страницу. Вот пример простой галереи, где каждая картинка будет полностью занимать один экран независимо от размеров окна браузера:
Размеры картинок задаются вот таким образом:
Ширина вьюпорта — 100vw . Это значение позволяет растянуть на ширину экрана любой элемент при любой вложенность.
Если задать элементу ширину 100% , получится ширина родителя, который, скорее всего, занимает только часть экрана, а 100vw позволяет растянуть именно на ширину окна браузера не обращая внимания на размеры родительских элементов.
Правда, тут есть проблема: 100vw — это ширина всего окна вместе с полосой прокрутки, а доступная для контента ширина окна полосу прокрутки не включает, из-за чего при попытке задать элементам ширину вьюпорта появится горизонтальный скролл:
Если нет возможности изменить вёрстку, чтобы избежать использования 100vw , можно задать overflow-x: hidden ближайшему родителю, растянутому на ширину страницы:
Проблема с полосами прокрутки будет видна только в десктопных браузерах, потому что на мобильных скроллбар размещается поверх страницы и не занимает пространство.
Если вы верстаете на MacOS, и полосы прокрутки исчезают сами по себе, выберите в System Perefences/General опцию «Показывать всегда», это позволит верстать страницы сразу с учетом сколлбаров:

Используя vw и vh можно делать полностью резиновые элементы, которые будут сами подстраиваться под размер окна, например, так:
Лучше всего открыть это демо в отдельной вкладке и порастягивать окно браузера.
С помощью vmin можно сделать элемент, который всегда будет целиком помещаться в экран, сохраняя пропорции:
Это демо тоже лучше смотреть в отдельной вкладке, попробуйте порастягивать окно по вертикали и по горизонтали.
В отличие от единиц, привязанных к шрифту, единицы вьюпорта не реагируют на масштабирование страницы. Откройте это демо и поизменяйте масштаб используя Ctrl+ / Ctrl- . Текст, размер которого задан в rem , будет увеличиваться и уменьшаться, текст с размером, заданным в vw , останется неизменным.
Пример с единицами вьюпорта ведёт себя совершенно логично, потому что масштабирование не меняет размер окна. Об этой особенности нужно помнить, если вы захотите использовать единицы вьюпорта для задания размера текста — пользователь не сможет сделать такой текст покрупнее.
В качестве решения предлагается примешивать единицы вьюпорта к относительным единицам измерения, привязанным к размеру шрифта, например, так:
Вживую можно потестить здесь, пример взят из этой статьи. Больше про управление размером шрифта с помощью единиц вьюпорта можно почитать тут.
За дополнение про особенности масштабирования спасибо @bekharsky.
У единиц, привязанных к размерам вьюпорта, могут быть проблемы с поддержкой в IE включая 11-й, поэтому обязательно проверяйте код в действующем браузере.
В спецификации описано немного больше единиц измерения, например:
- cap — высота заглавной буквы
- lh — высота строки
- rlh — высота строки корневого элемента
Но в данный момент они нигде не поддерживаются, поэтому в статье не рассматриваются.
width
The width CSS property sets an element’s width. By default, it sets the width of the content area, but if box-sizing is set to border-box , it sets the width of the border area.
Try it
The min-width and max-width properties override width .
Syntax
Values
Defines the width as a distance value.
Defines the width as a percentage of the containing block’s width.
The browser will calculate and select a width for the specified element.
The intrinsic preferred width.
The intrinsic minimum width.
Uses the fit-content formula with the available space replaced by the specified argument, i.e. min(max-content, max(min-content, <length-percentage>)) .
Accessibility concerns
Ensure that elements set with a width aren’t truncated and/or don’t obscure other content when the page is zoomed to increase text size.
What are the accepted units for the <img> width attribute?
I’m new to html so I’m a bit lost when I read that we can change the dimensions of the images through CSS or the width, height attribute.
For the width height attribute, some posts say that only pixels are accepted. But somehow, percentage also seems to work fine for my code.
However, when I tried using vw and vh, the image sized strangly.
- What are the accepted units for width and height attribute?
- Is CSS recommended over width and height, for changing the dimensions of the images?
1 Answer 1
The accepted units for the width and height attributes of an HTML img element are pixels. You give the number of pixels, but don’t put the ‘px’.
width The intrinsic width of the image in pixels. Must be an integer without a unit.
It is possible to get confused between these attributes and the use of CSS properties of the same names. While the attributes had more use probably when load times were longer (they allowed the correct space for the img to be saved in the page) they may be making a comeback, see https://developer.mozilla.org/en-US/docs/Web/Media/images/aspect_ratio_mapping which ends with:
— eliminating another piece of jank from web layout! There is no need for a web developer to do anything special to their code to take advantage of this, besides returning to the habit of using width and height attributes in their HTML.