When working with creative designers on web page designs, it’s fairly common to receive multiple Sketch or Photoshop artboards/layouts, one for each breakpoint.

In that design, elements (like an h1 heading) will usually be different sizes at each breakpoint. For example:

The h1 at the small layout could be 22px

at the small layout could be The h1 at the medium layout could be 24px

at the medium layout could be The h1 at the large layout could be 34px

The bare minimum CSS for this uses media queries:

h1 {

font-size: 22px;

}

@media (min-width:576px) {

h1 {

font-size: 22px;

}

}

@media (min-width:768px) {

h1 {

font-size: 24px;

}

}

@media (min-width:992px) {

h1 {

font-size: 34px;

}

}

This is good, but it’s a little bit jolting when you resize your browser window. At each breakpoint, the text size instantly jumps up/down in size. It would be great if the resizing of fonts between layouts was completely fluid. Your layout is fluid. Why not your font-sizes too? You could throw in a CSS transition to smooth out that jump:

h1 {

font-size: 22px;

transition: font-size 0.2s;

}

It’s not so jarring now, but the jump is still clearly there. What else can we do?

Viewports Units to the rescue?

Viewport units are a step in the right direction. They allow your text to fluidly resize with your layouts. And the browser support is great these days.

But the viability of Viewport units is very dependent on the original creative designs for a web page. It would be great to just set your font-size using vw and be done:

h1 {

font-size: 2vw;

}

But this only works if your creative art-boards take this into account. Did the designer choose a text size that was exactly 2% of the width of each of his art-boards? Of course not. Let’s calculate what the vw value would need to be for each of our breakpoints:

22px size @ 576px wide = 22/576 = 3.82% of the width

24px size @ 768px wide = 24/768 = 3.13% of the width

34px size @ 992px wide = 34/992 = 3.43% of the width

They are close but they aren’t all the same. So you would still need to use media queries to transition between text sizes but there would still be jumps. And consider this weird side-effect:

@ 767px, 3.82% of the viewport width is 29px. Resizing your browser 1-pixel wider and the font-size sudden drops back down to 24px. That would be weird.

So how do we solve this problem?

Statistical Linear Regression?

Wait. What? Yes, this is an article about CSS, but some basic math can go a long way towards an elegant solution to our problem.

First, lets plot our resolutions and corresponding text sizes on a graph:

Scatter plot of font-size and corresponding Viewport width (Google Spreadsheets)

Here you can see a scatter plot of the designer’s specified text sizes at the defined viewport widths. See that line? That‘s’ called a trendline. It’s sort of a way for you to find an interpolated font-size value for any viewport width, based on the data we provided.

The trendline is the key to all of this

If you could set your font-size according to this trendline, you would have an h1 that smoothly scales on all resolutions that would come close to matching what the designer intended. First, let’s look at the math. The straight line is defined by this equation:

Linear equation definition

m = slope

b = the y-intercept.

x = the current viewport width

y = the resulting font-size

The are several methods for determining the slope and y-intercept. A common method is the Least Squares fit:

Once you run those calculations, you have your trendline equation.

How do I use this in CSS?

Okay, this is getting pretty heavy on the math. How do I actually use this stuff in front-end web development? The answer is CSS calc() ! Once again, a fairly new CSS technology that is very well supported

You can use the trendline equation like this:

h1 {

font-size: calc({slope}*100vw + {y-intercept}px);

}

Once you find your slope and y-intercept you just plug them in and Viola!

Note: You have to multiply the slope by 100 since you are using it as a vw unit which is 1/100th of the Viewport width.

Can this be automated?

I ported the least squares fit method into an easy-to-use SASS function:

Does this really work? Open up this CodePen and resize your browser window. It works! The font sizes are fairly close to what the original design was asking for and they smoothly scale with your layout.