Daniel Pietzsch

Personal blog. Mostly photos.

CSS width-based font size

For one-column responsive layouts – like this blog for example – I like using width-based font sizes. Using the vw (view width) unit, the font size automatically scales based on the width of the viewport. It’s perfectly responsive without the need for media query breakpoints (at least initially, see below).

Here’s what I found to be a good calculation:

body {
  // 1em minimum font size (usually 16px) plus
  // 0.7% of the browser window’s total width
  font-size: calc(1em + 0.7vw);
}

This however stops working as intended, once the viewport starts becoming wider than the container the text resides in. It’s very common (for me anyway) to specify a maximum width of the main element that holds the text. But vw takes into account the width of the whole browser window, which inappropriately keeps increasing the font size, while the container width remains at the maximum width specified.

For example, this blog currently specifies a max-width of 700 pixels for its main content. So, I’d like to calculate font size based on the container width of 700px instead of the whole browser window width:

@media (min-width: 701px) {
  body {
    font-size: calc(1em + 700px * 0.007);
  }
}

However, since the calculation is static, I ended up simply calculating it myself in ems and use that:

@media (min-width: 701px) {
  body {
    font-size: 1.306em;
  }
}

Can’t we just get max-font-size?

A note on CSS variables

While deciding on these statements above, I also tried out CSS variables to store certain values like the max-width of the container etc. to calculate the font-size like so:

:root {
  --container-max-width: 100vw;
  --base-font-size: 1em;
  --container-fraction: 0.007; /* 0.7% */
}

body {
  font-size: calc(
    var(--base-font-size) +
    var(--container-fraction) *
    var(--container-max-width));
}

@media (min-width: 701px) {
  body {
    --container-max-width: 700px;
  }
}

But with this I

  1. need a breakpoint anyway to either redefine a variable or the calculation and
  2. I’d need additional fallback statements for browsers that don’t understand CSS vars.

So, I decided against using them. For a more complex project, this might be a different story, but for a simple site with a pretty static design, that’d be total overkill and backwards in my opinion.