Viewport sized typography with minimum and maximum sizes

Viewport units for typography are quite a cool toy to have in your responsive web design toolbox, as they allow you to size fonts relatively to the dimensions of the viewport. If you’ve never used them before, Chris Coyier’s article is probably a good place to start.

These units can produce really interesting results, but they must be used with caution. From my experience, there’s always a point where the font becomes unreadable on small screens, and sometimes too big on large screens. I end up setting a couple of media queries to set some boundaries on where the viewport units kick in.

As a result, I created a Sass mixin that abstracts what I wish you could more naturally in CSS: specify a minimum and a maximum size for the font while still using viewport based units. The mixin takes the viewport based size, a minimum value (in pixels), an optional maximum value (in pixels as well) and an optional fallback value, in whatever units you prefer, for browsers that don’t support viewport units.

///
/// 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;
}

Caveat: vw or vh units work, vmin or vmax don’t.

Here’s a pen showing the effect.

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

What are your thoughts? ∎

Comments

Lorenzo

Wednesday, June 24th, 2015, 07.47am

Thank you for this helpful and inspiring mixin! However, I think sizing fonts relatively to the dimensions of the viewport could be a problem with accessibility. It doesn't allow to increase the font size using the shortcut of the browser (cmd/ctrl +)

Igi Manaloto

Wednesday, June 24th, 2015, 01.23pm

Gave this a try. I've never really used vw/vh units except for this one odd project I was doing... This is quite an interesting approach! I'll try this first thing tomorrow.

Those who are using it, make sure you specify a pixel, percentage, em or rem size beforehand so unsupported or partially browsers (IE cough cough cough cough cough cough) can cope: http://caniuse.com/#feat=viewport-units

So thanks, hope to read more from you!

Thomas

Wednesday, June 24th, 2015, 05.02pm

Be careful with this: user-initiated zoom (ctrl/cmd + +) will NOT size the font, as the viewport stays the same, because we are using viewport units here. That's a huge accessibility issue to consider before using this. Otherwise, this is awesome :-)

Alex

Monday, September 12th, 2016, 11.47am

Hi there,

I was trying to use the code you provide but the text comes up in a bigger font size when viewed on laptops screen. When resizing the browser or on mobile devices, works fine.

The text is at the bottom of the front page.

have you any idea on how to fix this issue?

Regards,

Alex

Leave a comment