This Sass mixin allows you to create fluid font sizes that will scale responsively based on the viewport width. It takes two arguments:
- Min font size: The minimum font size in pixels.
- Max font size: The maximum font size in pixels.
- (optional) Min viewport width: The minimum viewport width in pixels.
- (optional) Max viewport width: The maximum viewport width in pixels.
The mixin will then calculate a fluid font size that falls within that range, based on the current viewport width.
/**
* Fluid Typography | SASS mixin with clamp() - @include fluid-font-size()
* @param {$min_font_size} - Number in px
* @param {$max_font_size} - Number in px,
* @param {$min_viewport} - Number in px (optional | default 576px)
* @param {$max_viewport} - Number in px (optional | default 1366px)
* @returns - Font Size using clamp()
*
* Gist: https://gist.github.com/iamsaief/dad6b1d3b4bb96d374d415cff0e01dfd
*/
@use "sass:math";
@mixin fluid-font-size($min_font_size, $max_font_size, $min_viewport: 576px, $max_viewport: 1366px) {
font-size: clamp(
$min_font_size,
get-fluid-size($min_font_size, $max_font_size, $min_viewport, $max_viewport),
$max_font_size
);
}
@function get-fluid-size($min_font_size, $max_font_size, $min_viewport, $max_viewport) {
$min_font_size_in_rem: #{math.div(strip-unit($min_font_size), 16)}rem;
$font_size_diff: strip-unit($max_font_size) - strip-unit($min_font_size);
$viewport_diff: strip-unit($max_viewport) - strip-unit($min_viewport);
$fluid_size: calc($min_font_size_in_rem + $font_size_diff * ((100vw - $min_viewport) / ($viewport_diff)));
@return $fluid-size;
}
@function strip-unit($number) {
@if type-of($number) == "number" and not unitless($number) {
@return math.div($number, ($number * 0) + 1);
}
@return $number;
}
// $fluid-sizes($name, $max, $min)
$fluid-sizes: (
"h1" 60px 48px,
"h2" 48px 36px,
"h3" 36px 30px,
"h4" 30px 24px,
"h5" 24px 20px,
"h6" 20px 18px,
"p" 16px 14px
);
@each $name, $max, $min in $fluid-sizes {
.fluid-text-#{$name} {
@include fluid-font-size($min, $max);
}
}
There are 3 ways to use the mixin:
- As a utility class: You can apply these classes to your elements or you could create your own utility classes.
- @include mixin: You can also use the mixin directly in your Sass code.
- @extend utility class: You can also use the @extend at-rule to extend the utility classes created by the mixin.
<!-- Usage #1 - as utility class -->
<h1 class="fluid-text-h1">I am heading 1</h1>
<h2 class="fluid-text-h2">I am heading 2</h2>
...
...
<h6 class="fluid-text-h6">I am heading 6</h6>
<!-- utility classes
.fluid-text-h1 {
font-size: clamp(48px, 3rem + 12 * (100vw - 576px) / 790, 60px);
}
.fluid-text-h2 {
font-size: clamp(36px, 2.25rem + 12 * (100vw - 576px) / 790, 48px);
}
...
...
.fluid-text-h6 {
font-size: clamp(18px, 1.125rem + 2 * (100vw - 576px) / 790, 20px);
}
-->
// Usage #2 - @include mixin
body {
@include fluid-font-size(14px, 16px);
}
// Usage #3 - @extend utility class
h1 {
@extend .fluid-text-h1;
}