megclaypool
7/10/2018 - 8:01 PM

Fluid Responsive Typography With CSS Poly Fluid Sizing

Fluid Responsive Typography With CSS Poly Fluid Sizing

https://www.smashingmagazine.com/2017/05/fluid-responsive-typography-css-poly-fluid-sizing/

A Few Notes: Obviously this method applies not only to font-size but to any unit/length property (mar

/// linear-interpolation
/// Calculate the definition of a line between two points
/// @param $map - A SASS map of viewport widths and size value pairs
/// @returns A linear equation as a calc() function
/// @example
///   font-size: linear-interpolation((320px: 18px, 768px: 26px));
/// @author Jake Wilson <jake.e.wilson@gmail.com>
@function linear-interpolation($map) {
  $keys: map-keys($map);
  @if (length($keys) != 2) {
    @error "linear-interpolation() $map must be exactly 2 values";
  }
  // The slope
  $m: (map-get($map, nth($keys, 2)) - map-get($map, nth($keys, 1)))/(nth($keys, 2) - nth($keys,1));
  
  // The y-intercept
  $b: map-get($map, nth($keys, 1)) - $m * nth($keys, 1);
  
  // Determine if the sign should be positive or negative
  $sign: "+";
  @if ($b < 0) {
    $sign: "-";
    $b: abs($b);
  }
  
  @return calc(#{$m*100}vw #{$sign} #{$b});
}
/// list-remove
/// Remove an item from a list
/// @param $list - A SASS list
/// @param $index - The list index to remove
/// @returns A SASS list
/// @author Jake Wilson <jake.e.wilson@gmail.com>
@function list-remove($list, $index) {
  $newList: ();
  @for $i from 1 through length($list) {
    @if $i != $index {
      $newList: append($newList, nth($list,$i), 'space');
    }
  }
  @return $newList;
}
/// list-sort
/// Sort a SASS list
/// @param $list - A SASS list
/// @returns A sorted SASS list
/// @requires function list-remove
/// @author Jake Wilson <jake.e.wilson@gmail.com>
@function list-sort($list) {
  $sortedlist: ();
  @while length($list) > 0 {
    $value: nth($list,1);
    @each $item in $list {
      @if $item < $value {
        $value: $item;
      }
    }
    $sortedlist: append($sortedlist, $value, 'space');
    $list: list-remove($list, index($list, $value));
  }
  @return $sortedlist;
}
/// map-sort
/// Sort map by keys
/// @param $map - A SASS map
/// @returns A SASS map sorted by keys
/// @requires function list-sort
/// @author Jake Wilson <jake.e.wilson@gmail.com>
@function map-sort($map) {
  $keys: list-sort(map-keys($map));
  $sortedMap: ();
  @each $key in $keys {
    $sortedMap: map-merge($sortedMap, ($key: map-get($map, $key)));
  }
  @return $sortedMap;
}
/// poly-fluid-sizing
/// Generate linear interpolated size values through multiple break points
/// @param $property - A string CSS property name
/// @param $map - A Sass map of viewport unit and size value pairs
/// @requires function linear-interpolation
/// @requires function map-sort
/// @example
///   @include poly-fluid-sizing('font-size', (576px: 22px, 768px: 24px, 992px: 34px));
/// @author Jake Wilson <jake.e.wilson@gmail.com>
@mixin poly-fluid-sizing($property, $map) {
  // Get the number of provided breakpoints
  $length: length(map-keys($map));

  // Error if the number of breakpoints is < 2
  @if ($length < 2) {
    @error "poly-fluid-sizing() $map requires at least values"
  }

  // Sort the map by viewport width (key)
  $map: map-sort($map);
  $keys: map-keys($map);

  // Minimum size
  #{$property}: map-get($map, nth($keys,1));

  // Interpolated size through breakpoints
  @for $i from 1 through ($length - 1) {
    @media (min-width:nth($keys,$i)) {
      $value1: map-get($map, nth($keys,$i));
      $value2: map-get($map, nth($keys,($i + 1)));
      // If values are not equal, perform linear interpolation
      @if ($value1 != $value2) {
        #{$property}: linear-interpolation((nth($keys,$i): $value1, nth($keys,($i+1)): $value2));
      } @else {
        #{$property}: $value1;
      }
    }
  }

  // Maxmimum size
  @media (min-width:nth($keys,$length)) {
    #{$property}: map-get($map, nth($keys,$length));
  }
}