Skip to content

Sass Fluid Typography

Fluid typography scales smoothly between a minimum and maximum size as the viewport changes, avoiding the abrupt jumps that come from switching font sizes at fixed breakpoints. This lesson shows how to compute a fluid clamp() value with a Sass function.

What Is Fluid Typography?

Fluid typography uses the CSS clamp() function to define a minimum size, a preferred, viewport-relative size, and a maximum size, so text scales continuously with the viewport instead of jumping between fixed sizes at specific breakpoints.

.hero-title {
  font-size: clamp(1.75rem, 4vw + 1rem, 3rem);
}

This clamps the title's font size between 1.75rem and 3rem, growing smoothly with viewport width in between.

The clamp() Formula

clamp(minimum, preferred, maximum)
  • minimum is the smallest allowed size, used on the smallest screens.
  • preferred is usually a formula combining a viewport unit (vw) and a fixed unit (rem).
  • maximum is the largest allowed size, used on the largest screens.
  • Hand-calculating the preferred formula for a specific min/max/viewport range is tedious, a Sass function automates it.

Fluid Typography Cheatsheet

Common fluid type scale values using a min/max viewport range of 375px–1440px.

Role Min Size Max Size Example clamp()
Body text 1rem 1.125rem clamp(1rem, 0.9vw + 0.8rem, 1.125rem)
Heading (h3) 1.25rem 1.75rem clamp(1.25rem, 1.5vw + 1rem, 1.75rem)
Heading (h2) 1.75rem 2.5rem clamp(1.75rem, 2.5vw + 1.2rem, 2.5rem)
Heading (h1) 2.25rem 3.5rem clamp(2.25rem, 3.5vw + 1.5rem, 3.5rem)

A Sass Function for Fluid Type

Rather than hand-calculating the viewport-based formula for every heading, a single Sass function can compute the correct clamp() value from just a min size, max size, and viewport range.

@use 'sass:math';

@function fluid-size($min, $max, $min-vw: 375px, $max-vw: 1440px) {
  $slope: math.div($max - $min, $max-vw - $min-vw);
  $intercept: $min - $slope * $min-vw;

  @return clamp(
    #{$min},
    #{$intercept} + #{$slope * 100vw},
    #{$max}
  );
}

h1 {
  font-size: fluid-size(2.25rem, 3.5rem);
}

The function computes the linear formula (slope and intercept) connecting the min size at the min viewport to the max size at the max viewport.

Using a Fluid Type Scale Map

Combine fluid-size() with a token map (as covered in the Design Tokens lesson) to define a full type scale in one place, generating consistent fluid sizes for every heading level.

$type-scale: (
  h1: (2.25rem, 3.5rem),
  h2: (1.75rem, 2.5rem),
  h3: (1.25rem, 1.75rem),
);

@each $tag, $sizes in $type-scale {
  #{$tag} {
    font-size: fluid-size(nth($sizes, 1), nth($sizes, 2));
  }
}

Fluid Typography and Accessibility

Always test fluid type against browser zoom and user-controlled font-size preferences. Because clamp()'s bounds are absolute, extremely aggressive minimums or maximums can still interfere with users who need larger text; verify real-world zoom behavior, not just the visual design at default settings.

Common Mistakes

  • Hardcoding a clamp() formula manually for every heading instead of computing it consistently with a shared function.
  • Choosing a minimum size that's too small to remain legible and accessible on small screens.
  • Forgetting to test fluid type against actual browser zoom and OS-level font-size accessibility settings.
  • Using vw alone without a fixed component, which can make text size depend too heavily on viewport width alone.

Key Takeaways

  • Fluid typography uses clamp() to scale text size smoothly between a minimum and maximum bound.
  • A Sass function can compute the linear clamp() formula automatically from just min size, max size, and a viewport range.
  • Combine a fluid-size function with a type scale map for a consistent, maintainable heading system.
  • Always test fluid type against zoom and accessibility font-size settings, not just the default viewport.

Pro Tip

Keep your min and max sizes reasonably close together (roughly a 1.4×–1.6× ratio) rather than an extreme range, this produces smoother, more natural-feeling scaling than a dramatic jump between the smallest and largest viewport.