Don’t hesitate to contact us if you have any feedback.

SCSS – Min-Max interpolation

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 rem as 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:


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *