Skip to Main Content (Press Enter)

Fluid Typography Tool

Use this highly customizable tool to create masterful websites with the power of fluid typography – an advanced CSS technique wherein the font's size and line height adjusts proportionally to the viewport's width.

Viewport Width Range

Set the "breakpoints" at which the font's size and line height should stop changing as the viewport's width changes.

px
px

Font Size Range

Set the font size range to correlate with the viewport width's range (i.e. Start will be the font size at the start of the viewport width's range; End will be the font size at the end of the viewport width's range).

px
px

Line Height Range

Set the line height range to correlate with the viewport width's range (i.e. Start will be the line height at the start of the viewport width's range; End will be the line height at the end of the viewport width's range).

The quick brown fox jumps over the lazy dog

Instead of setting media query breakpoints, use fluid typography to create a more "fluid" (or gradual) transition between font sizes and line heights that change proportionally according to the width of the viewport.

A combination of mathematics and CSS's clamp() function are used to achieve this effect.

Responsive Font Size

In responsive web design, we use media query breakpoints in order to make a website's content respond in a certain way depending on the viewport's width.

Consider the following example of responsive font size :

@media (max-width: 414px) {
  h1 {
    font-size: 16px;
  }
}

@media (min-width: 415px) and (max-width: 768px) {
  h1 {
    font-size: 32px;
  }
}

@media (min-width: 769px) {
  h1 {
    font-size: 48px;
  }
}

The CSS defines the font-size property of the h1 element when the viewport is at various breakpoints.

  • For viewports up to 414px wide, the font size is 16px.
  • For viewports between 415px and 768px, the font size is 32px.
  • For viewports of at least 769px wide, the font size is 48px.
#

This responsive approach causes the font size to "jump" from 16px to 32px when the viewport's width goes from 414px to 415px. This "jump" from one font size to another also happens when the width goes from 768px to 769px, or from 769px to 768px, or from 415px to 414px.

Basic Fluid Font Size

One way to avoid this "jump" side effect (and achieve a more "fluid" effect, instead) is to use the viewport's current width — as opposed to using predefined breakpoints — when setting the font size. We can do this by using CSS's viewport unit for width: vw.

There are four viewport-based units in CSS:

  • vw
  • vh
  • vmin
  • vmax

vw is a relative length unit representing a percentage of the viewport's width. For example, 50vw is 50% of the viewport's width. So, given a viewport that is 1280px wide, 50vw means 50% of that 1280px, which is 640px

You can learn more about viewport-based units on the MDN Web Docs .

Let's update our example and set the font-size property of the h1 element to 10vw :

h1 {
  font-size: 10vw;
}

As the viewport's width changes, the value of the font-size property adjusts proportionally:

  • When the viewport's width is 400px, the font-size property is set to 10% of 400px, which is 40px.
  • When the viewport's width is 800px, the font-size property is set to 10% of 800px, which is 80px.
#

The changes to the font size will now present with fluidity.

Intermediate Fluid Font Size

One drawback to setting the value of the font-size property to a vw unit is precision control. What if you wanted the font size to be:

  • 32px when the viewport's width is 414px,
  • 48px when the viewport's width is 768px, and
  • proportionally in between 32px and 48px when the viewport's width is in between 414px and 768px?

A simple assignment of a vw value to the font-size property is no longer an option. Instead, we need to use a combination of CSS's calc() function and a couple of mathematical formulas.

According to the MDN Web Docs,

The calc() CSS function lets you perform calculations when specifying CSS property values.

And for the purpose of fluid font size, the calc() function will suffice.

The first mathematical formula we need to be aware of is the point-slope form equation of a line:

y - y1 = m(x - x1)

Where:

  • y = y coordinate of the second point
  • y1 = y coordinate of the first point
  • m = slope of the line formed by the two points with coordinates (x, y) and (x1, y1)
  • x = x coordinate of the second point
  • x1 = x coordinate of the first point

y represents the unknown font size for a given viewport width (x). The coordinates (x1, y1) represent any given point on the line.

Before we can use the point-slope form, we first need to compute what slope m is. The formula to calculate slope m (also known as the gradient of a line) is:

m = (y2 - y1) / (x2 - x1)

Where:

m = slope of the line formed by the two points (x1, y1) and (x2, y2)
  • (x1, y1) = coordinates of the first point
  • (x2, y2) = coordinates of the second point

We want our font size to be 32px when the viewport is 414px wide. So, let:

  • x1 = 32px
  • y1 = 414px

Thus, the coordinates of our first point are:

(414, 32)

We want our font size to be 48px when the viewport is 768px wide. So, let:

  • x2 = 768px
  • y2 = 48px

Thus, the coordinates of our second point are:

(768, 48)

Now, let's plug in the given values to the formula m = (y2 — y1) / (x2 — x1) to compute our slope:

  1. m = (48 - 32) / (768 - 414)
  2. m = 16 / 354
  3. m = 0.04519774011

Now that we have the value of slope m, we can get back to our point-slope form:

y - y1 = m(x - x2)

Note that the coordinates (x1, y1) represent a point on the line with a slope m = 0.04519774011 (based on our previous calculations).

Using the formula y — y1 = m(x — x1), we can now solve for the unknown font size (y) when viewport width (x) is, for example, 591px (which is halfway between 414px and 768px; we can intuitively estimate that the unknown font size (y) should therefore be halfway between 32px and 48px):

  1. y - 32 = 0.04519774011 (591 - 414)
  2. y - 32 = 0.04519774011 (177)
  3. y - 32 = 7.9999999977
  4. y = 7.9999999977 + 32
  5. y = 39.9999999977

As expected, font size (y) is halfway between 32px and 48px.

Now, how do we use all this math in CSS to achieve fluid font size? This is where the CSS calc() function comes in.

Let's update our example to use CSS's calc() function :

:root {
  /* Declare without units so we can compute the slope */
  --min-vw: 414;
  --max-vw: 768;
  --min-h1-font-size: 32;
  --max-h1-font-size: 48;

  /* m = (y2 - y1) / (x2 - x1)  */
  --rise: calc(var(--max-h1-font-size) - var(--min-h1-font-size));
  --run: calc(var(--max-vw) - var(--min-vw));
  --slope: calc(var(--rise) / var(--run));
}

h1 {
  /* Due to the way addition and subtraction works in calc(),
  we need to "type cast" --min-vw and --min-h1-font-size to appropriate units */
  --min-vw-px: calc(var(--min-vw) * 1px);
  --min-h1-font-size-px: calc(var(--min-h1-font-size) * 1px);

  /* y - y1 = m(x - x1) */
  --fluid-font-size-px:
    calc(
      var(--slope) * (100vw - var(--min-vw-px)) + var(--min-h1-font-size-px)
    );

  font-size: var(--fluid-font-size-px);
}

The key to making fluid font size work in our example is the use of 100vw for the value of x in the point-slope formula.

#

We have now achieved the precision control we were aiming for. When the viewport's width is 414px, the font size is 32px. When the viewport's width is 768px, the font size is 48px. Solving for any other viewport width (x) and font size (y) on the same line with a slope of m = 0.04519774011, we can use the point-slope formula y — 32 = 0.04519774011(x — 414).

Advanced Fluid Font Size

Another drawback of setting the font-size property to a vw unit is that this may result in extremely small or large font sizes. What if you wanted the font size to never go below 32px or above 48px?

In order to set boundaries for the font size, we need to use CSS's clamp() function.

According to the MDN Web Docs,

the clamp() CSS function clamps a value between an upper and lower bound. clamp() enables selecting a middle value within a range of values between a defined minimum and maximum. [It] takes three comma separated expressions as its parameter, in the order of minimum value, preferred value, maximum value.

So, if we were to set the first parameter to 32px and the third parameter to 48px, we would have a font size that would never go below 32px or above 48px.

Let's update our example to use CSS's clamp() function :

:root {
  /* Declare without units so we can compute the slope */
  --min-vw: 414;
  --max-vw: 768;
  --min-h1-font-size: 32;
  --max-h1-font-size: 48;

  /* m = (y2 - y1) / (x2 - x1) */
  --rise: calc(var(--max-h1-font-size) - var(--min-h1-font-size));
  --run: calc(var(--max-vw) - var(--min-vw));
  --slope: calc(var(--rise) / var(--run));
}

h1 {
  /* Due to the way addition and subtraction works in calc(),
  we need to "type cast" --min-vw and --min-h1-font-size to appropriate units */
  --min-vw-px: calc(var(--min-vw) * 1px);
  --min-h1-font-size-px: calc(var(--min-h1-font-size) * 1px);

  /* y - y1 = m(x - x1) */
  --fluid-font-size-px:
    calc(
      var(--slope) * (100vw - var(--min-vw-px)) + var(--min-h1-font-size-px)
    );

  /* "Type cast" --max-vw to px */
  --max-h1-font-size-px: calc(var(--max-h1-font-size) * 1px);

  font-size:
    clamp(
      var(--min-h1-font-size-px),
      var(--fluid-font-size-px),
      var(--max-h1-font-size-px)
    );
}

As you can see, when the viewport is 414px and below, the font size is 32px. And when the viewport is 768px and above, the font size is 48px. The font size is only fluid when the viewport's width is between 414px and 768px.

#

Some Final Thoughts

That depends on the devices your website needs to support and the aesthetics you wish to achieve.

Ideally, you would base your range on your website's statistics. Absent that, you can review a worldwide screen resolution statistics resource.

Pick a font size that is readable and accessible. For websites, regardless of device, the general consensus seems to be:

  • Primary text should be 16px
  • Secondary text should be about 2px smaller than the primary text (so, about 13px or 14px)
  • Text input should be at least 16px (so, about 18px)

As for headings, this is where you have the most flexibility to take advantage of fluid typography. Headings tend to be bigger than the primary text and therefore have the most room to resize.

For ideal readability, aim for a line height that is about 130% to 150% the size of the font (so, 1.3 to 1.5). For optimal readability and accessibility, try 140% to 180% (that's 1.4 to 1.8).

Smaller fonts require more line height, which is why you may want to specify a start line height that has a greater value than the end line height (assuming your font size is adjusting proportionally to the viewport's width).