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

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

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

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 :-)

Rob Morrow

Friday, June 26th, 2015

Not everyone uses Sass or Less. Can it be done in CSS? And, why are comments here appearing 2-3 times?

Diego F.

Saturday, June 27th, 2015

Awesome tut! Be sure to check out the very simple jquery fontFlex plugin for an alternative

https://github.com/nathco/jQuery.fontFlex

Alex

Monday, September 12th, 2016

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

Joe

Tuesday, June 27th, 2017

this works perfect! thanks!.. this is almost essential, I don't get why its not part of standard css.

Andrew

Tuesday, August 8th, 2017

What would this look like if I wanted it to listen to not just the viewport width but also the height at the same time.

Mike M

Wednesday, November 29th, 2017

Just wanted to point out that the min & max font-sizes only work when you specify the font-size in pixels - the calculated media queries for ems and rems is wrong.

Leave a comment