- PVSM.RU - https://www.pvsm.ru -
Уверен, что никому не нужно объяснять почему сайты должны быть гибкими и адаптивными. Все используют проценты и медиа-запросы в своей верстке. Сейчас это уже стандарт.
Но типографика до недавнего времени не была столь гибкой. Все что мы могли — изменять размеры шрифта от брейкпоинта к брейкпоинту. В таком случае мы получали скорее адаптивную типографику нежели отзывчивую. Для каждого медиа-запроса нужно задавать свои значения. Можно конечно использовать компонентный подход с относительными размерами шрифта, что может существенно ускорить процесс редактирования, но принципиально это ничего не меняет. При перемещении компонента в другое место нужно будет опять пробегать по всем медиа запросам и подставлять новые значения.
Но потом появились они — vw, vh, vmin, vmax — единицы измерения, которые базируются на viewport. У нас появился шанс на отзывчивую типографику.
100vw равно ширине (100vh — высоте) экрана в пикселях (или будет приведено к другим величинам если использовать в calc()). 100vmax — равно большему из пары высота/ширина, 100vmin — меньшему. Сразу же начали появляться рецепты [1] использования этих чудо величин в типографике.
Но в таком виде их сложно контролировать. Иногда [2] попадались рецепты с использованием каких-то магических процентных величин. Но меня не устраивал вариант разбираться откуда они, а потом считать или подбирать вручную их для получения нужных мне размеров в моих условиях.
Хотелось иметь универсальный рецепт, который позволял бы задавать минимальное и максимальное значения для размера шрифта, да еще и привязать эти цифры к конкретным размерам viewport. Например, при ширине экрана в 480px иметь ровно 16px, а при 1280px — 24px.
Вспомнив курс школьной математики пришел к выводу что моя задача не что иное, как уравнение прямой проходящей через 2 точки. Первая точка — меньшая ширины экрана и размер шрифта на ней, вторая — бОльшая ширина и соответствующий ей размер шрифта.
На оси X — ширина окна браузера, на оси Y — наш размер шрифта. Получаем уравнение с двумя неизвестными:
откуда
y — наш неизвестный размер шрифта, x — текущий размер экрана. x1 — минимальное значение шрифта, x2 — максимальное значение шрифта. y1 и y2 минимальное и максимальные значение ширины экрана соответственно.
А теперь самое интересное: имея CSS функцию calc() и текущее значение вьюпорта благодаря vw можно получить динамический размер шрифта:
font-size: calc( (100vw - Vmin)/(Vmax - Vmin) * (Fmax - Fmin) + Fmin);
Эту формулу уже можно использовать в чистом CSS. Только нужно помнить, что при операциях умножения/деления хотя бы один из аргументов должен быть без единиц измерения, а при сложение/вычитании — оба с единицами. Подставив наши значения получим рабочий вариант (обратите внимание на использование единиц измерения):
font-size: calc( (100vw - 480px)/(1280 - 480) * (24 - 16) + 16px);
Единицы измерений можно использовать любые, главное, чтобы они совпадали. Тоже самое, только в rem:
font-size: calc( (100vw - 30rem)/(80 - 30) * (1.5 - 1) + 1rem);
Имея под рукой такой инструмент как Sass можно большую часть вычислений спрятать от браузера.
Для этого больше подойдет следующее уравнение прямой:
Коеффициенты k и b можно получить из уравнения прямой по двум точкам:
Получим функцию:
@function calcFluidFontSize($f-min, $f-max, $v-min, $v-max) {
$k: ($f-max - $f-min)/($v-max - $v-min);
$b: $f-min - $k * $v-min;
$b: $b * 1px;
@return calc( #{$k} * 100vw + #{$b} );
}
.fluid-font-size {
font-size: calcFluidFontSize(16, 48, 480, 1280);
}
В случае, если мы хотим иметь возможность использовать не только px но и другие единицы измерений, можно передавать их одним из параметров:
@function calcFluidFontSize($f-min, $f-max, $v-min, $v-max, $units: px) {
$k: ($f-max - $f-min)/($v-max - $v-min);
$b: $f-min - $k * $v-min;
$b: $b + $units;
@return calc( #{$k} * 100vw + #{$b} );
}
.fluid-font-size {
font-size: calcFluidFontSize(1, 3, 30, 80, rem);
}
Для защиты от неверно введенных данных, можно обрезать единицы измерений при получении данных. Для этого можно использовать функцию strip-unit [3] или взять ее из библиотеки bourbon [4]:
@function strip-unit($number) {
@if type-of($number) == 'number' and not unitless($number) {
@return $number / ($number * 0 + 1);
}
@return $number;
}
@function calcFluidFontSize($f-min, $f-max, $w-min, $w-max, $units: px) {
$f-min: strip-unit($f-min);
$f-max: strip-unit($f-max);
$w-min: strip-unit($w-min);
$w-max: strip-unit($w-max);
$k: ($f-max - $f-min)/($w-max - $w-min);
$b: $f-min - $k * $w-min;
$b: $b + $units;
@return calc( #{$k} * 100vw + #{$b} );
}
Функцию для вычисления размера шрифта мы имеем. Теперь на ее основе можно создать миксин, который можно расширять как угодно.
Например, мы хотим фолбек для старых браузеров:
@mixin fluidFontSize($f-min, $f-max, $w-min, $w-max, $fallback: false) {
@if ($fallback) {
font-size: $fallback;
}
font-size: calcFluidFontSize($f-min, $f-max, $w-min, $w-max, px);
}
.fluid-font-size {
@include fluidFontSize(16px, 24px, 480px, 1280px, 18px);
}
Теперь можно в качестве фолбека передавать оптимальный размер шрифта на случай, когда vw не поддерживается.
Можно ограничить размеры шрифта нашим минимальным и/или максимальным значением:
@mixin fluidFontSize($f-min, $f-max, $w-min, $w-max, $fallback: false) {
font-size: $f-min;
@media (min-width: $w-min) {
@if ($fallback) {
font-size: $fallback;
}
font-size: calcFluidFontSize($f-min, $f-max, $w-min, $w-max, px);
}
@media (min-width: $w-max) {
font-size: $f-max;
}
}
.fluid-font-size {
@include fluidFontSize(16px, 24px, 480px, 1280px, 18px);
}
Теперь при ширине экрана меньше 480px шрифт всегда будет 16px, после 480 он станет резиновым, а после 1280px всегда будет 24px.
Мы получили базовую функцию, которая выполняет весь основной функционал:
@function calcFluidFontSize($f-min, $f-max, $w-min, $w-max, $units: px) {
$f-min: strip-unit($f-min);
$f-max: strip-unit($f-max);
$w-min: strip-unit($w-min);
$w-max: strip-unit($w-max);
$k: ($f-max - $f-min)/($w-max - $w-min);
$b: $f-min - $k * $w-min;
$b: $b + $units;
@return calc( #{$k} * 100vw + #{$b} );
}
Для ее расширения использовались миксины, с помощью которых можно сделать фоллбеки, ограничения, конвертацию единиц измерения и многое другое. Поиграться со всем этим можно на codepen [5]. Если Вы не хотите использовать Sass здесь [6] вы найдете способ вычислений на чистом CSS.
» The Lengths of CSS [7]
» REM vs EM – The Great Debate [8]
» Viewport Sized Typography [1]
» Truly Fluid Typography With vh And vw Units [9]
» Viewport Unit Based Typography [2]
Автор: ROBsoer
Источник [10]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/sass/188248
Ссылки в тексте:
[1] рецепты: https://css-tricks.com/viewport-sized-typography/
[2] Иногда: https://zellwk.com/blog/viewport-based-typography/
[3] strip-unit: https://css-tricks.com/snippets/sass/strip-unit-function/
[4] bourbon: http://bourbon.io/docs/#strip-units
[5] codepen: http://codepen.io/ROBsoer/pen/PGkWbK
[6] здесь: http://codepen.io/ROBsoer/pen/xEwaGd
[7] The Lengths of CSS: https://css-tricks.com/the-lengths-of-css/
[8] REM vs EM – The Great Debate: https://zellwk.com/blog/rem-vs-em/
[9] Truly Fluid Typography With vh And vw Units: https://www.smashingmagazine.com/2016/05/fluid-typography/
[10] Источник: https://habrahabr.ru/post/310186/?utm_source=habrahabr&utm_medium=rss&utm_campaign=sandbox
Нажмите здесь для печати.