📜 ⬆️ ⬇️

Responsive Font Size

I am sure that no one needs to explain why websites should be flexible and adaptive. All use percentages and media queries in their layout. Now it is already standard.


But typography, until recently, was not so flexible. All we could do was change the font size from breakpoint to breakpoint. In this case, we received rather adaptive typography rather than responsive. For each media query you need to set your own values. You can of course use the component approach with relative font sizes, which can significantly speed up the editing process, but in principle this does not change anything. When moving a component to another location, you will need to again run through all media queries and substitute new values.


But then they appeared - vw , vh , vmin , vmax - units of measurement, which are based on the viewport. We have a chance for responsive typography.



An overview of viewport-dependent units.


100vw is equal to the width ( 100vh - height) of the screen in pixels (or will be converted to other values ​​if used in calc () ). 100vmax - equal to the larger of the pair height / width, 100vmin - smaller. Immediately began to appear recipes for the use of these miracle values ​​in typography.


But in this form they are difficult to control. Sometimes there were recipes using some kind of magic percentage. But I was not satisfied with the option to figure out where they came from, and then read or manually select them to get the dimensions I needed in my conditions.


Task


I wanted to have a universal recipe that would allow to set the minimum and maximum values ​​for the font size, and even link these numbers to specific viewport sizes. For example, with a 480px screen width, have exactly 16px , and at 1280px - 24px .


Solution path


Remembering the course of school mathematics I came to the conclusion that my task is nothing but the equation of a straight line passing through 2 points. The first point is the smaller screen width and font size on it, the second is the larger width and the corresponding font size.



On the X axis - the width of the browser window, on the Y axis - our font size. We obtain an equation with two unknowns:


{x-x_1 \ over x_2-x_1} = {y-y_1 \ over y_2-y_1}


from where


y = {x-x_1 \ over x_2-x_1} (y_2-y_1) + y_1


y is our unknown font size, x is the current screen size. x 1 - the minimum value of the font, x 2 - the maximum value of the font. y 1 and y 2 are the minimum and maximum screen widths, respectively.


And now the most interesting thing: having the CSS function calc () and the current viewport value, thanks to vw, you can get a dynamic font size:


font-size: calc( (100vw - Vmin)/(Vmax - Vmin) * (Fmax - Fmin) + Fmin); 

This formula can already be used in pure CSS. It is only necessary to remember that during multiplication / division operations, at least one of the arguments must be without units, and during addition / subtraction, both with units. Substituting our values ​​we get the working version (note the use of units of measurement):


 font-size: calc( (100vw - 480px)/(1280 - 480) * (24 - 16) + 16px); 

You can use any units of measurement, as long as they match. Same as rem only:


 font-size: calc( (100vw - 30rem)/(80 - 30) * (1.5 - 1) + 1rem); 

Use Sass / SCSS


Having a tool like Sass at hand can hide most of the calculations from the browser.
For this, the following equation of a straight line is more suitable:


y = kx + b


The coefficients k and b can be obtained from the equation of a straight line at two points:


k = {y_2-y_1 \ over x_2-x_1}


b = y_1- {y_2-y_1 \ over x_2-x_1} x_1 = y_1-kx_1


We get the function:


 @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); } 

In case we want to be able to use not only px but also other units of measurement, we can transfer them with one of the parameters:


 @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); } 

To protect against incorrectly entered data, you can cut off the units when receiving data. To do this, you can use the strip-unit function or take it from the bourbon library:


 @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} ); } 

We extend the capabilities of our function.


The function for calculating the font size we have. Now, on its basis, you can create a mixin that can be expanded as you like.


For example, we want folbek for old browsers:


 @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); } 

Now it is possible to transfer the optimal font size as a foldback in case vw is not supported.


You can limit the font sizes to our minimum and / or maximum values:


 @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); } 

Now, with a screen width less than 480px, the font will always be 16px , after 480 it will become rubber, and after 1280px there will always be 24px .


Result


We got a basic function that performs all the basic functionality:


 @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} ); } 

For its expansion, mixins were used, with the help of which you can make fallbacks, restrictions, unit conversion and much more. You can play with all this on the codepen . If you do not want to use Sass here you will find a way to do pure CSS calculations.


Read


» The Lengths of CSS
REM vs EM - The Great Debate
» Viewport Sized Typography
» Truly Fluid Typography With vh And vw Units
» Viewport Unit Based Typography


')

Source: https://habr.com/ru/post/310186/


All Articles