Responsive design often requires fluid scaling of elements to fit different screen sizes. A typical use case is scaling typography, where font sizes should adjust between a minimum and maximum size based on the viewport/container-size. To facilitate this, we use min-max interpolation techniques.
SCSS Helper Functions
The SCSS code includes several functions designed to enable fluid typography:
get-unit Function
Extracts the unit from a numerical value, which is useful for unit conversions.
@use 'sass:string';
@function get-unit($value) {
@return string.slice($value * 0 + '', 2, -1);
}
strip-unit Function
Removes the unit from a number, allowing for unitless calculations within SCSS.
@use 'sass:math';
@use 'sass:meta';
@function strip-unit($number) {
@if meta.type-of($number) == 'number' and not math.is-unitless($number) {
$temp: $number * 0 + 1;
@return calc($number / ($temp));
}
@return $number;
}
calculateRem Function
Converts pixel values to rem units, facilitating relative sizing based on a base font size.
@function calculateRem($size) {
@return calc(($size / 16) * 1rem);
}
min-max-interpolation Function
Calculates a clamp() value for fluid scaling between two values over a range of viewport sizes.
@use 'sass:string';
@use 'sass:math';
@function min-max-interpolation($min-value, $max-value, $min-breakpoint, $max-breakpoint, $container-unit: 1vw) {
@if get-unit($min-value) == 'px' {
$min-value: calculateRem(strip-unit($min-value));
}
@if math.is-unitless($min-value) {
$min-value: calculateRem($min-value);
}
@if get-unit($max-value) == 'px' {
$max-value: calculateRem(strip-unit($max-value));
}
@if math.is-unitless($max-value) {
$max-value: calculateRem($max-value);
}
@if get-unit($min-breakpoint) == 'px' {
$min-breakpoint: calculateRem(strip-unit($min-breakpoint));
}
@if math.is-unitless($min-breakpoint) {
$min-breakpoint: calculateRem($min-breakpoint);
}
@if get-unit($max-breakpoint) == 'px' {
$max-breakpoint: calculateRem(strip-unit($max-breakpoint));
}
@if math.is-unitless($max-breakpoint) {
$max-breakpoint: calculateRem($max-breakpoint);
}
$factor: calc(1 / ($max-breakpoint - $min-breakpoint) * ($max-value - $min-value));
$calc-value: string.unquote('#{$min-value - ($min-breakpoint * $factor)} + #{calc((100 * $container-unit) * $factor)}');
@return clamp(#{if($min-value > $max-value, $max-value, $min-value)}, #{$calc-value}, #{if($min-value > $max-value, $min-value, $max-value)});
}
Advantages
- Consistency: Ensures consistent scaling across different screen sizes.
- Customizable: Can be tailored to different scaling factors and breakpoints.
- Unit Conversion: Handles different units, converting pixels to
remas needed.
Example Usage
body {
// If you want the font size to be based on the screen size
font-size: min-max-interpolation(18px, 22px, 960px, 1200px);
// OR
font-size: min-max-interpolation(18, 22, 960, 1200);
// If you want the font size to be based on the size of the parent container
font-size: min-max-interpolation(18px, 22px, 960px, 1200px, 1cqw);
// OR
font-size: min-max-interpolation(18, 22, 960, 1200, 1cqw);
// Returns clamp( 1.125rem, 0.125rem + 1.6666666667vw, 1.375rem )
}
The above example sets the font size to scale between 18px and 22px as the viewport width/container width ranges from 960px to 1200px.
Inspiration
This approach to min-max interpolation is inspired by the following resources:

Leave a Reply