Размеры шрифтов css. пиксели vs em vs rem vs проценты vs viewport единицы

Таблица стилей типографики

Поэтому, когда дело доходит до перехода от дизайна к разработке, я просто добавляю значения rem к значениям px в таблицу стилей типографики

Важно иметь оба значения, поскольку дизайнерам, работающим с файлом, понадобятся пиксели

Таблица стилей типографики. Источник moonlearing.io

Кстати, в Figma фактические единицы пикселей безразмерны, я предполагаю, что это нужно, чтобы не путать пиксели, используемые для дизайна, и пиксели разрешения экрана (в Figma мы проектируем так называемое 1x, где 1px = 1pt, но это тема для отдельной статьи, следите за обновлениями и подписывайтесь на автора).

Не забудьте также перевести высоту строки в относительные единицы! В этом случае вам не нужно использовать rem, вы можете просто использовать безразмерное число, например, 1.5. Оно рассчитает высоту строки из заданного размера шрифта. Поэтому размер шрифта 16px и высота строки 1.5 приведут к 16px * 1.5 = высота строки 24px.

Вычисления в Figma

Если вы не знаете, то вы можете рассчитать что угодно прямо на панели свойств. Таким образом, вы можете просто разделить заданный размер шрифта на 16px и записать новое значение в таблицу стилей. Вам нужно снова умножить его на 16px, чтобы восстановить значение в пикселях. Для высоты строки, я просто использую %, так как для меня это намного проще, а затем перевожу их в таблице стилей, например, 150% в 1.5.

Используйте панель свойств как калькулятор

Плагин Hand >> over переведет для вас px в rem

Что такое CSS-шлюз?

Размеры относительно окна браузера

В последнем проекте у меня был баннер во всю ширину с заголовком сверху, причем макет был только для настольных ПК, с крупным шрифтом. Я решил, что мне нужен шрифт помельче для маленьких экранов и что-то промежуточное для средних. Почему бы не сделать шрифт зависимым от ширины окна?

Ранние подходы для этого выглядели примерно так:

h1 { font-size: 4vw; /* Бац! Готово. */ }

У этого было два недостатка:

  1. Текст становится совсем мелким на маленьких экранах (12.8 пикселей при 320px) и очень крупным на больших (64px при 1600px);
  2. Он не реагирует на пользовательские настройки для размера шрифта.

Техники CSS-шлюзов призваны исправить первый пункт. Отличные техники CSS-шлюзов стараются исправить и второй: учет пользовательских предпочтений.

Понятие CSS-шлюза

CSS-шлюз — такой способ вычисления CSS-значения, при котором:

  • есть минимальное и максимальное значения,
  • есть две контрольные точки (обычно отталкивающиеся от ширины окна)
  • и между этими контрольными точками фактическое значение линейно меняется от минимума до максимума.

«Пусть у нас font-size будет 20px при 320px и меньше, 40px при 960px и выше, а в промежутке его значение меняется от 20px до 40px».

В CSS это может выглядеть так:

h1 { font-size: 1.25rem; }

@media (min-width: 320px) {
  h1 { font-size: /* магическое значение от 1.25rem  до 2.5rem */; }
}

@media (min-width: 960px) {
  h1 { font-size: 2.5rem; }
}

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

h1 {
  font-size: calc(1.25rem + значение_относительно_окна);
}

Где может быть отдельным значением (напр., 3vw) или более сложным выражением (тоже на основе единицы vw или другой единицы области просмотра).

Ограничения

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

Почему в пикселях? Потому что единицы области просмотра (, , и ) всегда в конечном итоге переводятся в пиксели. Например, при ширине окна 768px переводится в 7.68px.

(У Тима в статье есть ошибка, где он пишет, что выражение типа переводится в em. Это не так: браузер воспримет как значение в пикселях, и вычтет из него столько пикселей, сколько их окажется в для этого элемента и этого свойства.)

Несколько примеров того, что работать не будет:

  • CSS-шлюз для свойства opacity, потому что — это ошибка;
  • CSS-шлюз для большинства функций (напр., нельзя повернуть что-либо на столько-то пикселей)

Что ж, на первый взгляд с одними лишь пикселями особо не разгуляешься, но, может быть, кто-то возьмет на себя смелость отыскать все свойства и приемы, где от CSS-шлюзов может быть польза.

Для разминки, возьмем свойства и и посмотрим, как построить для них CSS-шлюзы с контрольными точками как в пикселях, так и в em-ах.

Practical Application

There may be some debate among web designers and I’m sure different people have different preferred approaches, however my recommendation is as follows.

Use Units For:

Any sizing that should scale depending on the font-size of an element other than the root.

Generally speaking, the only reason you’ll need to use units is to scale an element which has non default font sizing.

As per our example above, design components like menu items, buttons, and headings may have their own explicitly stated font sizes. If you change these font sizes, you want the entire component to scale proportionately.

Common properties this guideline will apply to are , , , and settings, when used on elements with non default font sizing.

I recommend that when you do employ units, the font size of the element they’re used on should be set in units to preserve scalability but avoid inheritance confusion.

Typically Don’t Use Units for Font Sizes

It’s quite common to see units used for font sizing, particularly in headings, however I would suggest that designs are more manageable if units are typically used for font sizing.

The reason headings often use units is they’re a better choice than units, being relative to regular text size. However units can achieve this goal equally well. If any font size adjustment on the element is made, the heading sizes will still scale too.

Try changing the font size on the element in this CodePen to see for yourself:

More often than not, we don’t want our font sizes to scale based on any element other than the root, with only a few exceptions.

One example where we might want based font sizing could be a drop down menu, where we have second level menu item text sized depending on the font size of the first level. Another example might be a font icon used inside a button, where the icon’s size should relate to the button’s text size.

However most elements in a web design will tend not to have this type of requirement, so you’ll generally want to use units for font sizing, with units only where specifically needed.

Use units for:

Any sizing that doesn’t need units for the reasons described above, and that should scale depending on browser font size settings.

This accounts for almost everything in a standard design including most heights, most widths, most padding, most margins, border widths, most font sizes, shadows, basically almost every part of your layout.

In a nutshell, everything that can be made scalable with units, should be.

Tip

When creating layouts it’s often easier to think in pixels but output in units.

You can have pixel to calculations done automatically via a preprocessor like Stylus / Sass / Less, or a postprocessor like PostCSS with the PXtoRem plugin.

Alternatively, you can use PXtoEM to manually do your conversions.

Always Use Media Queries

Importantly, when using units to create a uniformly scalable design, your media queries should also be in units. This will ensure that whatever a user’s browser font size, your media queries will respond to it and adjust your layout.

For example, if a user scales up text very high, your layout may need to snap down from a two columns to a single column, just as it might on a smaller screened mobile device.

If your breakpoints are at fixed pixel widths, only a different viewport size can trigger them. However with based breakpoints they will respond to different font sizing too.

Don’t Use or For:

Multi Column Layout Widths

Column widths in a layout should typically be based so they can fluidly fit unpredictably sized viewports.

However single columns should still generally incorporate values via a setting.

For example:

This keeps the column flexible and scalable, but prevents it from becoming too wide for the text therein to be comfortably readable.

When an Element Should be Strictly Unscalable

In a typical web design there won’t be many parts of your layout that can’t be designed for scalability. However occasionally you will come across elements that really do need to use explicit fixed values for the purpose of preventing scaling.

The precondition for employing fixed sizing values should be that if the element in question were scaled it would break. This really doesn’t come up often, so before you’re tempted to whip out those units, ask yourself if using them is an absolute necessity.

Case 1: Properties of all Elements Scale With The Component’s Font-Size

Let’s begin with an example of what such a component looks like:

How component resizes (Case 1)

Notice how the , and of all elements within the component change at the same time?

If your component behaves in this manner when resized, you need to size everything in s. The code then becomes:

Then, to activate the change in sizes, all you have to do is to change the component’s property.

So far so good.

Now, let’s bring the complexity up a bit.

Imagine if you had a grid like this. The vertical and horizontal spaces between each grid item needs to remain the same across all devices (for good aesthetics).

Equal margins on a 1 + 2 grid!

The markup for this grid is:

I’ve set the gutter width between each grid item to be at a root of . In order words, the computed width of the gutter is .

The challenge in this grid is to separate small component A and small component B with a margin of . We can try setting a of component B to be for start.

Unfortunately, this doesn’t turn out well. The between small component A and small component B is larger than the gutter width at a viewport above 800px.

Space between the two smaller components isn’t equal to the gutters when the screen is wider than 800px

Boo :(

This happens because the of the component is (or ) when the viewport is larger than . Since the is , the computed value of becomes , which is different from the we were looking for.

Grrrrr! (╯°□°)╯︵ ┻━┻

Thankfully, we can solve this issue simply by sizing in since we know where the gutter width needs to be sized according to the root .

Vertical space is now equal! :)

Tada! Problem solved :) Here’s a Codepen for you to play with.

See the Pen REM vs EM – Case 1 by Zell Liew (@zellwk) on CodePen.

Note: You need to use Flexbox to build this grid. I won’t explain how I built it since it’s way out of scope. Check out this article if you’re interested in finding out more about Flexbox

Oh by the way, I didn’t come up with this technique. Chris Coyier wrote about it (he’s a genius).

Anyway, are we good so far? If yes, let’s move on to case 2. If not, feel free to leave a comment and I’ll figure a way to explain this further.

em Unit

em is borrowed from the typography world, and it’s a unit that allows setting the font-size of an element relative to the font-size of its parent.

Let’s take this simple example:

With that example, the child would have a font-size of 27px (1.5 * 18px = 27px).

If the parent element doesn’t specify a value for font-size, a value will be looked for higher up in the DOM tree. If no font-size is specified all the way up to the root element (), then the browser default of 16px is used.

Pretty simple and straight-forward right? em units can be used for much more than just setting font-size however, and they can be used pretty much everywhere units are expected (padding, margin, width, height, max-width,…you get the picture!) When em units are used on other properties than font-size, the value is relative to the element’s own font-size.

Let’s add to our example:

  • The padding top and bottom on will be 54px. That’s 2 times the font-size of our current element’s font size (2 * 27px)
  • The padding left and right on will be of 27px. That’s 1 time the font-size of our element.

Remember: when em units are used on font-size, the size is relative to the font-size of the parent. When used on other properties, it’s relative to the font-size of the element itself.

Compounding Effect: Trouble in Paradise

So far everything is well and good with using the em unit, but a problem can come about from the fact that the unit can compound from one level to the other.

Let’s keep a similar basic example:

But let’s use it in our markup like this:

I’m 15px I’m 30px, as expected I’m 60px, trouble starts! I’m 120px, now we’re really in trouble!

So, as you can see, the effect of em units can be compounding when multiple em-font-sized elements are within one another. This can become a problem and can lead to unintended consequences in your designs.

This problem is the reason why the rem unit was created.

What about media queries?

So we’ve established that using pixel values overrides browser default settings, so simply converting all pixel sizes to REMs is the best thing to do, right? Not quite.

This blog post highlights some of the key the differences between using pixels, EMs and REMs in media queries (https://zellwk.com/blog/media-query-units/). Go have a read and then come back.

In summary, both pixels and REMs for media queries fail in various browsers when using browser zoom, and EMs are the best option we have. REMs fail much more than pixels at this point, so we’re going to discount them completely.

It does get a bit more tricky though. Both EMs and pixels have their downfalls with media queries when it comes to the difference of a decimal place of that unit. If you happen to use both min and max width media queries in the same block of code, you’re going to have a bad time as soon as the user starts to change their browser zoom or default font-size.

Here are some examples:

We use 6 decimal places because certain browsers show no difference between 2-5.d.p.

For clarity, we’re using a font size of 10px on the body to make the maths a little clearer.

Example 1: Browser zoom set to 100%, browser width set to 640px

min-width: 64em = Hit
max-width: 63.99em = Miss
max-width: 63.999999em = Hit
min-width: 640px = Hit
max-width: 639px = Miss
max-width: 639.999999px = Miss

Example 1b: Browser zoom set to 100%, browser width set to 639px

min-width: 64em = Miss
max-width: 63.99em = Hit
max-width: 63.999999em = Hit
min-width: 640px = Miss
max-width: 639px = Hit
max-width: 639.999999px = Hit

So we can’t use 6dp for EMs, because it hits both media queries.

Example 2: Browser zoom set to 110%, browser width set to 704px (because 640px * 110% = 704px)

min-width: 64em = Miss
max-width: 63.99em = Miss
max-width: 63.999999em = Hit
min-width: 640px = Miss
max-width: 639px = Miss
max-width: 639.999999px = Hit

Example 2b: Browser zoom set to 110%, browser width set to 705px

min-width: 64em = Hit
max-width: 63.99em = Miss
max-width: 63.999999em = Miss
min-width: 640px = Hit
max-width: 639px = Miss
max-width: 639.999999px = Miss

So we can’t use 2dp for EMs. So all we’re left with at this stage is 6dp pixels. This works with browser zoom. However…

Example 3: Browser zoom set to 100%, browser font size set to 20px, browser width set to 800 (because 640 * 125% = 800)

min-width: 64em = Hit
max-width: 63.99em = Miss
max-width: 63.999999em = Hit

So again, 6dp EMs are still out. And we can’t use pixels for media queries at all, because they still fire at 640px/639px because they ignore EMs/REMs.

The Effect of Inheritance on em Units

Working with units can start to get tricky when it comes to inheritance, because every element automatically inherits the font size of its parent. The effect of inheritance can only be overridden by explicitly setting a font size with a unit not subject to inheritance, such as or .

The font size of the element on which units are used determines their size. But that element may have inherited a font size from its parent, which inherited a font size from its parent, and so on. As such it’s possible for any value to be effected by the font size of any of its parents.

Let’s look at an example. Feel free to try this out in CodePen for yourself as we step through it. As you go along, use Chrome Developer Tools or Firebug for Firefox to inspect the pixel values our units are computed into.

Example of Inheritance

If we have a page with a root font size of (usually the default) and a child div inside it with padding of , that div will inherit the font size of from the root element. Hence its padding will translate to , i.e. 1.5 x 16 = 24.

Then what if we wrap another div around the first and set its to ?

Our wrapper div inherits the root font size of and multiplies that by its own setting of . This sets the div to have a font size of , i.e. 1.25 x 16 = 20.

Now our original div is no longer inheriting directly from the root element, instead it’s inheriting a font size of from its new parent div. Its padding value of now equates to , i.e. 1.5 x 20 = 30.

This scaling effect can be compounded even further if we add an based font size to our original div, let’s say .

The div inherits the font size from its parent, then multiplies that by its own setting, giving it a new font size of , i.e. 1.2 x 20 = 24.

The padding on our div will now change in size again with the new font size, this time to , i.e. 1.5 x 24 = 36.

Finally, to further illustrate that units are relative to the font size of the element they’re used on, (not the parent element), let’s see what happens to our padding of if we explicitly set the div to use a font size of , a value not subject to inheritance.

Now, our padding has dropped down to 21px, i.e. 1.5 x 14 = 21. It is unaffected by the font size of the parent element.

With all this potential for complication, you can see why its important to know how to use units in a manageable way.

Подожди, так в чем же загвоздка?

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

Медиа-запросы (использование )

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

Здесь значение изменяется в зависимости от того, применяется ли медиа-запрос, а медиа-запрос зависит от значения , так что же, черт возьми, происходит?

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

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

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

Сафари

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

Переключение контекста

Если вы переключаетесь между проектами, разными проектами, вполне возможно, что видимый размер шрифта будет иметь разные значения. В одном проекте вы можете использовать очевидный размер, а в другом — очевидный размер . Это может сбивать с толку и вызывать проблемы.

Моя единственная рекомендация — придерживаться преобразования до видимого размера , потому что в моем опыте это было более распространено.

Общие библиотеки CSS

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

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

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

Когда в CSS использовать rem, em, px, или что-то другое

Использование только px (пикселей) для CSS-размеров шрифта, контейнеров, отступов, позиционирования и пр. — путь простой, но тупиковый.

  • % , fr и flex-grow — эти единицы измерения лучше использовать для установки размеров контейнерам
  • px лучше использовать для установки размеров декоративных элементов, например, border
  • для определения высоты строки ( line-height ) лучше вообще не использовать единицы измерения и оставить только число
  • rem — для всего остального: размеров шрифта, полей, отступов, минимальной ширины и точек @media

Что такое rem?

rem (как и em ) относительная единица измерения. em может быть немного сложным в использовании, поэтому часто лучше придерживаться rem . Вот как rem работает:

  • rem — это единица измерения, относительно размеров корневого элемента («r» в rem означает: root).
  • Допустим, браузер считает базовый размер шрифта 16px . Этот размер указан для корневого элемента (он же элемент html )

Таким образом, если нужно, чтобы какой-то размер был эквивалентен 14px , достаточно посчитать его отношение к базовому размеру: 14/16 = 0.875rem .

Почему rem?

Относительные единицы предпочтительнее пикселей, потому что они учитывают предпочтения пользователя и настройки его браузера. Браузер позволяет пользователю изменить размер шрифта по умолчанию. Это значение применяется к размеру шрифта по умолчанию для корневого элемента. Поскольку rem вычисляется относительно размера основного шрифта, то размеры, указанные в rem будут пропорционально масштабироваться.

Таким образом, rem можно использовать практически для всех случаев. Например, для: font-size , margin , padding , min-width и т.д.

Есть ли у rem какие-либо недостатки?

Использование rem в медиа-запросах (@media), для минимальной или максимальной ширины, может быть проблематичным из-за того, что браузеры использует разные методы округления дробных чисел.

Но настоящий недостаток, это неинформативность дробных относительных значений и необходимость их пересчета, чтобы осознать размер в привычных пикселях. Например, при просмотре кода не очевидно, что min-width: 18.75rem это — 300px из макета. Немного поправить эту проблему можно, реализуя в препроцессоре функцию, которая будет выполнять вычисления и поможет прояснить, что происходит. В SCSS это может быть так:

Когда использовать px?

Чем реже — тем лучше. Пиксели следует использовать, когда размеры являются декоративными и/или не нуждаются в масштабировании относительно, предпочитаемого пользователем, размера шрифта. Отличный вариант использования px — границы (border). Чаще всего нет необходимости масштабировать их относительно размеров шрифта.

Как насчет %, fr, flex-grow?

Контейнерные элементы — это те, которые содержат контент. Это прямоугольники, которые содержат текст, изображения и другие элементы контейнера. Они обычно нуждаются в указании размеров и расположения. Размеры контейнерных элементов следует указывать с использованием относительных значений: проценты, fr (для CSS grid) или flex-grow (для flexbox). Это гарантирует, что элемент контейнера будет изменять свои размеры относительно размеров окна браузера.

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

Когда единицы измерения можно не указывать?

Из всего сказанного до сих пор, есть одно исключение: line-height (высота строки).

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

So what’s the solution?

Unfortunately, there isn’t an answer. Until browsers sort out rounding issues, we’re a bit stuck.

The simplest acceptable option, is that we never create a min-width and max-width overlap in the same block. Example:

body {
    @media screen and (max-width: 63.99em) {
        background: blue;
    }
    @media screen and (min-width: 64em) {
        background: blue;
    }
}

The problem with the above is that there are certain scenarios where both media queries are hit, or both are ignore. So the safe bet would be to write something like:

body {
    background: blue;
    @media screen and (min-width: 64em) {
        background: blue;
    }
}

Why isn’t there a real solution? I don’t believe enough people care. Any statistics saying that people don’t change their default browser font-size are definitely skewed. The options in Chrome to change the default font-size is now very buried in the advanced browser options.

Pitfalls

There are some pitfalls to this approach:

  • If you’re used to writing both min-width and max-width media queries in the same code block, it will take longer.
  • It increases complexity as you’ll have to override CSS one direction or the other, rather than telling the browser to use option A or B.
  • It will increases file size due to these overrides. Not by much, but it’s worth considering.

Depending on the project, who’s developing it, and various other factors such as project budgets (we have to be realistic here), pixels might be easier and quicker. It also might be easier and quicker to ignore accessibility.

Remember who you’re building websites for.

It’s also worth noting that this blog post is accurate at the time of writing, but with the constant updates to the way browsers work, this issue could become a thing of the past.

Рейтинг
( Пока оценок нет )
Editor
Editor/ автор статьи

Давно интересуюсь темой. Мне нравится писать о том, в чём разбираюсь.

Понравилась статья? Поделиться с друзьями:
Люкс-хост
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: