Fluid Typography

Getting right to the code, here's a working implementation:

html {
  font-size: 16px;
}
@media screen and (min-width: 320px) {
  html {
    font-size: calc(16px + 6 * ((100vw - 320px) / 680));
  }
}
@media screen and (min-width: 1000px) {
  html {
    font-size: 22px;
  }
}

That would scale font-size from a minimum of 16px (at a 320px viewport) to a maximum of 22px (at a 1000px viewport). Here's a demo of that, but as a Sass @mixin (which we'll cover later).

See the Pen Base Example of Fluid Type w Sass by Chris Coyier (@chriscoyier) on CodePen.

Sass was used just to make that output a little easier to generate, and the fact that there is a smide of math involved. Let's take a look.

Using viewport units and calc(), we can have font-size (and other properties) adjust their size based on the size of the screen. So rather than always being the same size, or jumping from one size to the next at media queries, the size can be fluid.

Here's the math, credit Mike Riethmuller:

body {
  font-size: calc([minimum size] + ([maximum size] - [minimum size]) * ((100vw - [minimum viewport width]) / ([maximum viewport width] - [minimum viewport width])));
}

The reason that math is a little complicated is that we're trying to avoid type ever getting smaller than our minimum or bigger than our maximum, which is very easy to do with viewport units.

For example, if we want the our font size in a range where 14px is the minimum size at the smallest viewport width of 300px and where 26px is the maximum size at the largest viewport width of 1600px, then our equation looks like this:

body {
  font-size: calc(14px + (26 - 14) * ((100vw - 300px) / (1600 - 300)));
}
The text changes fluidly to the width of the viewport

See the Pen JEVevK by CSS-Tricks (@css-tricks) on CodePen.

To lock in those minimum and maximum sizes, using this math within media queries helps. Here's some Sass to help out...

In Sass

You could make a (pretty robust) mixin, like this:

@function strip-unit($value) {
  @return $value / ($value * 0 + 1);
}

@mixin fluid-type($min-vw, $max-vw, $min-font-size, $max-font-size) {
  $u1: unit($min-vw);
  $u2: unit($max-vw);
  $u3: unit($min-font-size);
  $u4: unit($max-font-size);

  @if $u1 == $u2 and $u1 == $u3 and $u1 == $u4 {
    & {
      font-size: $min-font-size;
      @media screen and (min-width: $min-vw) {
        font-size: calc(#{$min-font-size} + #{strip-unit($max-font-size - $min-font-size)} * ((100vw - #{$min-vw}) / #{strip-unit($max-vw - $min-vw)}));
      }
      @media screen and (min-width: $max-vw) {
        font-size: $max-font-size;
      }
    }
  }
}

Which you use like this:

$min_width: 320px;
$max_width: 1200px;
$min_font: 16px;
$max_font: 24px;

html {
  @include fluid-type($min_width, $max_width, $min_font, $max_font);
}

Here's another of Mike's examples, getting fluid rhythm just right:

Extending the Idea to Headers with Modular Scale

Modular scale, meaning the more space available, the more dramatic the different in size is. Perhaps at the largest viewport with, each header up the hierarchy is 1.4x bigger than the next, but at the smallest, only 1.05x.

See view:

With our Sass mixin, that looks like:

$mod_1: 1.2; // mobile
$mod_2: 1.5; // desktop

h1 {  
  font-size: $mod_1*$mod_1*$mod_1*$mod_1 *1rem; 
  @include fluid-type($min_width, $max_width, $mod_1*$mod_1*$mod_1 *$min_font, $mod_2*$mod_2*$mod_2 *$min_font);
}
h2 {  
  font-size: $mod_1*$mod_1*$mod_1 *1rem; 
  @include fluid-type($min_width, $max_width, $mod_1*$mod_1*$mod_1 *$min_font, $mod_2*$mod_2*$mod_2 *$min_font);
}
h3 { 
  font-size: $mod_1*$mod_1 *1rem;
  @include fluid-type($min_width, $max_width, $mod_1*$mod_1 *$min_font, $mod_2*$mod_2 *$min_font);
}

Other Reading

Comments

  1. User Avatar
    Wilbert
    Permalink to comment#

    Very nice trick! How is the browser support? IE11+?

  2. User Avatar
    Jacob
    Permalink to comment#

    I was looking in to integrating this in to my workflow this morning, and you left out a pretty key thing here. This fluid font size calculation should be within a media query with the minimum and maximum viewports set. Otherwise, it’ll continue scaling past the minimum and maximum. See the original post here:

    https://madebymike.com.au/writing/fluid-type-calc-examples/

    • User Avatar
      Chris Coyier
      Permalink to comment#

      The Sass mixin is the whole kit-and-kaboodle that covers all that, beyond the basic concept.

  3. User Avatar
    Thomas Kimmich
    Permalink to comment#

    prove me wrong guys, but the pen above doesn’t work in Safari?

    Cheers

    Thomas

    • User Avatar
      Chris Coyier
      Permalink to comment#

      I think it has to do with live complication of viewport units in Safari. Like if you refresh the page, it’s right, it’s just not fluid as you resize. Bummer. Temporary bug, I would think. Still useful.

    • User Avatar
      Mike Riethmuller
      Permalink to comment#

      There’s a bug in some versions of Safari (and IE11) that means it won’t be calculated on resize but as Chris said it should be correct on first load.

      This covers the majority of situations. But I hear adding +100% at the end of the calculation will fix the resize bug in Safari.

    • User Avatar
      Thomas Kimmich
      Permalink to comment#

      After giving Chris’ shared Sass Mixin a try, it works a treat – even in Safari.

      Might it be an issue in CodePen then? I mean all shared pens are struggling in Safari (which is probably the new IE?)

      Just wanted to let you know and thanks for sharing this. Very cool.

      Cheers

      Thomas

    • User Avatar
      Thomas Kimmich
      Permalink to comment#

      oops – entirely missed your comment, Mike. Apologize.

      Cheers

      Thomas

  4. User Avatar
    dazzle
    Permalink to comment#

    Can anyone tell me where is the difference to vw?

    • User Avatar
      Chris Coyier
      Permalink to comment#

      This technique uses vw. Just not only vw, as then there is no way to control a minimum and a maximum or the other trickery presented here.

    • User Avatar
      dazzle
      Permalink to comment#

      Thanks for the answer.

      I often use vw, but on small devices the text sometimes becomes much too small. Then i correct it by using a media query for the small device and increase the font-size. And with this technique you dont need the media query, right?

  5. User Avatar
    Mike Riethmuller
    Permalink to comment#

    Hey Chris, it’s worth sharing these examples by James Nowland: http://codepen.io/jnowland/pen/GWgbMP/ he’s made a really neat mixin and some people may prefer this syntax.

  6. User Avatar
    Joe Hoeller
    Permalink to comment#

    I’ve been doing fluid text for the last 2.5y or so.

    I use vw’s and rem’s in same CSS property block.

    Even use it to treat an entire HTML object as one big design that scales.

    • User Avatar
      User
      Permalink to comment#

      Joe, care to hook up and exchange about this, I am also using it to style most of the elements on a page besides the typography to get a neatly flowing & fluid layout going, where can I reach you? Have some (possibly still half baked) pens and gists, perhaps you like to take a look?

  7. User Avatar
    User
    Permalink to comment#

    Just today I actually sent an email to Mike outlining a little issue I have with the fluid type Sass mixin, that being, when using it for more than one region/media query, it does produce multiple values for the same selector, see here https://www.sassmeister.com/gist/0a451c254e43c07a7e487771d3590476 (if the CSS is not compiled straight away add a space and remove it again in the SCSS and SassMeister will re-trigger the compilation process)

    I have not read it yet, the poly fluid post https://css-tricks.com/poly-fluid-sizing/ , it just hit my inbox and I am going there straight away, perhaps a solution lies there, because I think that is what I am after.

    And just like Joe Hoeller writes, not only using this for typography but all styling in the dom, going from extreme 50px width to 2500px and above, great fun and once you get the hang of it you get a truly impressive and responsive layout going.

Submit a Comment

Posting Code

You may write comments in Markdown. This makes code easy to post, as you can write inline code like `<div>this</div>` or multiline blocks of code in triple backtick fences (```) with double new lines before and after.

Code of Conduct

Absolutely anyone is welcome to submit a comment here. But not all comments will be posted. Think of it like writing a letter to the editor. All submitted comments will be read, but not all published. Published comments will be on-topic, helpful, and further the discussion or debate.

Want to tell us something privately?

Feel free to use our contact form. That's a great place to let us know about typos or anything off-topic.

icon-anchoricon-closeicon-emailicon-linkicon-logo-staricon-menuicon-nav-guideicon-searchicon-staricon-tag