Современный веб — зоопарк всевозможных устройств, на которых можно запустить браузер. Поэтому разработчики следят за тем, как сайт выглядит на разных мобильных устройствах, планшетах и настольных компьютерах.
Из-за маленьких экранов мобильных устройств стоит сокращать размер шрифтов и отступов на странице.
Самый распространённый способ это сделать — медиавыражения. Например:
.button {
padding-inline: 4px;
font-size: 1.25rem;
background: blue;
border: none;
border-radius: 4px;
}
@media screen and (width >= 760px) {
.button {
padding-inline: 12px;
font-size: 1.5rem;
border-radius: 6px;
}
}
У этого способа есть недостатки:
- приходится писать много кода
- хочется учитывать промежуточные значения для отступов и делать элементы на странице по-настоящему резиновыми
Допустим, задача — задать размер шрифта, который будет меняться в диапазоне от 480 до 1280 пикселей. Минимальный размер будет 2.25rem
, максимальный - 3rem
.
Какие есть способы это сделать?
Функция calc()
Эта функция используется для вычислений в CSS. В сочетании с единицей измерения vi
(процентная величина ширины области просмотра), она становится мощным инструментом для создания адаптивного интерфейса.
Определим разницу между максимальным и минимальным размерами шрифта. В нашем примере это будет: 3rem - 2.25rem = 0.75rem
.
Также определим разницу между значениями вьюпорта, предварительно преобразовав их значение в единицу rem
(зависит от значения <html>
, по‑умолчанию 16px
). Получаем (1280 / 16) - (480 / 16) = 50
.
Мы получили следующие значения:
- Минимальный размер шрифта:
2.25rem
- Максимальный размер шрифта:
3rem
- Разница между максимальным и минимальным размерами шрифта:
0.75rem
- Минимальный размер вьюпорта:
30rem (480px)
- Разница между максимальным и минимальным размерами вьюпорта:
50rem (800px)
Необходимая функция выглядит следующим образом:
Минимальный размер шрифта + Разница между максимальным и минимальным размерами шрифта * ((Ширина вьюпорта - Минимальный размер вьюпорта) / Разница между максимальным и минимальным размерами вьюпорта).
Итого получаем следующий результат:
.foo {
font-size: 2.25rem;
}
@media screen and (min-width: 480px) and (max-width: 1280px) {
.foo {
font-size: calc(2.25rem + 0.75 * ((100vi - 30rem) / 50));
}
}
@media screen and (min-width: 1280px) {
.foo {
font-size: 3em;
}
}
Стало лучше, но пока кода по-прежнему слишком много.
Функция clamp()
Функция clamp()
- более лаконичный способ задания значения в диапазоне между минимальным и максимальным значением CSS свойства.
Всё, что остаётся - это найти предпочитаемое значение размера шрифта.
На координатной плоскости по оси X располагаются значения ширины окна браузера, а по оси Y - значения CSS свойств. Определим точку пересечения графика функции с осью ординат. Для этого используется угловой коэффициент.
Угловой коэффициент, напомню, это отношение изменения координаты Y (двух точек) к изменению координаты X (двух точек). Найдём разность между значениями которые соответствуют координатам первой и второй точек. Разницу между максимальным и минимальным размерами шрифта разделим на разницу между максимальным и минимальным размерами вьюпорта (одновременно с этим конвертируем размеры вьюпорта из px в rem для удобства). Результат: (3 - 2.25) / ((1280 / 16) - (480 / 16)) = 0.015
Угловой коэффициент равен 0.015
. Теперь найдём пересечение по оси Y по формуле: минимальный размер вьюпорта, преобразованный в отрицательное число, умноженный на угловой коэффициент плюс минимальный размер шрифта: (0 - (480 / 16)) * 0.015 + 2.25 = 1.8
Предпочитаемое значение размера шрифта будет равно пересечению по оси Y + (угловой коэффициент * 100)vi.
.foo {
font-size: clamp(2.25rem, 1.8rem + 1.5vi, 3rem);
}
PostCSS плагин
Эта математика кажется утомительной, особенно если речь идёт о разработке большого веб-приложения или целой дизайн-системы.
Чтобы упростить задачу я создал соответствующий плагин postcss-responsive.
Для использования резиновой типографики в проекте достаточно установить PostCSS-плагин:
npm install --save-dev postcss-responsive
pnpm add --save-dev postcss-responsive
yarn add --dev postcss-responsive
Добавляем плагин в PostCSS конфиг:
{
"plugins": {
"postcss-responsive": {
"minWidth": 480,
"maxWidth": 1280
}
}
}
Теперь можно использовать функцию responsive()
в наших стилях, передав в неё минимальный и максимальный размеры шрифта. Значение вычислит PostCSS-плагин.
/* Input */
.foo {
font-size: responsive(2.25rem, 3rem);
}
/* Output */
.foo {
font-size: clamp(2.25rem, 1.8rem + 1.5vw, 3rem);
}
Этот плагин будет полезен не только для создания адаптивной типографики, но и для работы с другими свойствами CSS.
.container {
display: grid;
grid-template-columns: responsive(180px, 240px) 1fr;
grid-gap: responsive(8px, 16px);
padding: responsive(16px, 32px) responsive(16px, 24px);
font-size: responsive(1rem, 1.125rem);
line-height: responsive(1.5rem, 1.75rem);
}
Создавайте резиновые интерфейсы без медиавыражений.