Viewport Sized Typography with Minimum and Maximum Sizes

Avatar of Eduardo Bouças
Eduardo Bouças on

Declaring font sizes in viewport units can produce really interesting results, but it does come with challenges. There are no min-font-size or max-font-size properties in CSS, so edge cases where text gets too small or too big are difficult to deal with.

This Sass mixin makes use of media queries to define a minimum and maximum size for the font, in pixels. It also supports an optional parameter to serve as a fallback to browsers that don’t support viewport units.

As an example, this is how you’d define a font as 5vw constrained between 35px and 150px (with a fallback of 50px for non-supporting browsers):

@include responsive-font(5vw, 35px, 150px, 50px);

And here’s the full mixin:

///
/// Viewport sized typography with minimum and maximum values
///
/// @author Eduardo Boucas (@eduardoboucas)
///
/// @param {Number}   $responsive  - Viewport-based size
/// @param {Number}   $min         - Minimum font size (px)
/// @param {Number}   $max         - Maximum font size (px)
///                                  (optional)
/// @param {Number}   $fallback    - Fallback for viewport-
///                                  based units (optional)
///
/// @example scss - 5vw font size (with 50px fallback), 
///                 minumum of 35px and maximum of 150px
///  @include responsive-font(5vw, 35px, 150px, 50px);
///
@mixin responsive-font($responsive, $min, $max: false, $fallback: false) {
  $responsive-unitless: $responsive / ($responsive - $responsive + 1);
  $dimension: if(unit($responsive) == 'vh', 'height', 'width');
  $min-breakpoint: $min / $responsive-unitless * 100;
  
  @media (max-#{$dimension}: #{$min-breakpoint}) {
    font-size: $min;
  }
  
  @if $max {
    $max-breakpoint: $max / $responsive-unitless * 100;
    
    @media (min-#{$dimension}: #{$max-breakpoint}) {
      font-size: $max;
    }
  }
  
  @if $fallback {
    font-size: $fallback;
  }
  
  font-size: $responsive;
}

Demo

See the Pen Viewport sized typography with minimum and maximum sizes by Eduardo Bouças (@eduardoboucas) on CodePen.