Fluid Typography in Tailwind CSS: Fluid Type Plugin + Winden
Many people set font sizes in Tailwind CSS by adding breakpoint classes to every heading and repeating that on each page. In this video we set up fluid typography with the tailwindcss-fluid-type plugin by David Hellmann. We also do the clamp() math by hand so you can see how each size step is calculated, then turn heading sizes into reusable classes. The result: headings that scale with the screen, one config to control them, and no repeated font-size classes on every element.
This is the first of two typography videos. This one covers font sizes. The next one covers registering and applying custom fonts.
Typography introduction
Before you touch the config, you need to know how many text sizes your design really uses. If you skip this step, you end up with lots of one-off sizes that drift apart over time.
We start from the Sketch design of our eLearning landing page. The headings use BioRhyme ExtraBold and the body text uses Roboto. That's enough to plan a type scale.
Reviewing current styles
Many Tailwind users assume they can't reuse text styles and have to write classes on every element. That's wrong, and it's why typography gets repetitive.
Go through the design and match every text block to a level:
- The hero title is an H1. The "Why choose e-learn" title uses the same size. If you don't want two H1 tags on the page, make it an H2 and give it the H1 style.
- The section titles (Available Courses, Pricing, Testimonials) are H2.
- The smaller titles go down through H3, H4, H5 and H6.
- The remaining text is paragraph text.
We want these sizes to change smoothly with the viewport, not jump at each breakpoint. That's what the fluid type plugin does.
Fluid type plugin setup
With fluid sizes, each size step is a clamp() value. It grows between a minimum and maximum screen width, so you don't need a stack of md: and lg: classes. We use Tailwind Play to test it before moving it into a project.
This is the plugin's default config, as shown in Tailwind Play:
const FluidType = require('tailwindcss-fluid-type')
module.exports = {
mode: 'jit',
theme: {
fluidTypeSettings: {
},
fluidType: {
settings: {
fontSizeMin: 1.125,
fontSizeMax: 1.25,
ratioMin: 1.125,
ratioMax: 1.2,
screenMin: 20,
screenMax: 96,
unit: 'rem',
prefix: ''
},
values: {
'xs': [-2, 1.6],
'sm': [-1, 1.6],
'base': [0, 1.6],
'lg': [1, 1.6],
'xl': [2, 1.2],
'2xl': [3, 1.2],
'3xl': [4, 1.2],
'4xl': [5, 1.1],
'5xl': [6, 1.1],
'6xl': [7, 1.1],
'7xl': [8, 1],
'8xl': [9, 1],
'9xl': [10, 1],
}
},
},
variants: {},
corePlugins: {},
plugins: [FluidType],
}
What each setting does:
- fontSizeMin / fontSizeMax: the base font size on the smallest and largest screen.
- ratioMin / ratioMax: how much each step grows compared to the step below it, on small and large screens.
- screenMin / screenMax: the screen widths where the scale stops shrinking and stops growing.
- unit:
remorpx. - prefix: optional. If you add a prefix, only classes that use it get fluid sizes. The rest keep Tailwind's default sizes. This is useful if you want to switch over one size at a time.
In values, the first number is the step and the second is the line height.
To make the math easier to follow, we changed the settings to pixels: fontSizeMin 15, fontSizeMax 20, ratioMin 1.1, ratioMax 1.1, screenMin 400, screenMax 1000, unit 'px'.
We kept the same ratio for min and max only to make the example easier to follow. In a real project you usually use a bigger ratio on desktop. You have more room there and want more contrast between heading sizes. On mobile you have less space, so you keep the sizes closer together.
Understanding multipliers
If you know how the plugin gets each number, you can pick settings on purpose instead of guessing. The rule is simple: each step multiplies the size below it by the ratio.
- base is step
0, so it stays at the base size: 15px on small screens, 20px on large screens. - lg is step
1: 20 × 1.1 = 22px at the max size. - xl is step
2, which multiplies by 1.1 again: 24.2px. - 2xl is step
3: about 26.62px.
In DevTools, under Computed → font-size, text-lg shows the clamp() the plugin generated:
clamp(16.5px, calc(16.5px + ((22 - 16.5) * ((100vw - 400px) / (1000 - 400)))), 22px)
16.5 is 15 × 1.1 (the smallest size), 22 is 20 × 1.1 (the largest size), and the font scales between them from 400px to 1000px screen width.
xs and sm use negative steps (-2 and -1), so they make the text smaller than base instead of larger.
Applying reusable classes
At this point you're still putting a text-* class on every heading, which brings the repetition back. Instead, set each heading's size once in CSS. Pair it with a matching class so any element can look like an H1 without being an H1.
- Remove the size classes from the headings in the HTML.
- In the CSS tab, target the tag and a class with the same name, and apply a fluid size:
@tailwind base;
@tailwind components;
@tailwind utilities;
.legend{
@apply uppercase text-gray-400 text-xs border-t mt-4 pt-2;
}
h1, .h1{
@apply text-8xl;
}
h2, .h2{
@apply text-4xl;
}
h3, .h3{
@apply text-2xl;
}
- Every
h1on the page now gets the size and scales with the viewport. - To make an H2 look like an H1 (the second "H1" in our design), add
class="h1"to it. You keep the right heading structure for SEO and accessibility and still get the design you want.
To change a heading size across the whole site, you edit one line. Once the config works in Tailwind Play, copy it into Winden's config and it works there the same way.
Who is this for
- WordPress site builders using Tailwind CSS through Winden who are tired of adding responsive font-size classes to every heading.
- Developers who want font sizes to scale smoothly between mobile and desktop instead of jumping at breakpoints.
- Anyone who has used the fluid type plugin but didn't know how its
clamp()values are calculated. - Teams that want one place to control heading sizes so every page stays consistent.
FAQ
How does tailwindcss-fluid-type calculate font sizes?
Each step multiplies the base font size by the ratio once per step. With a base of 20 and a ratio of 1.1, step 1 (lg) is 22, step 2 (xl) is 24.2 and step 3 (2xl) is about 26.62. The plugin does this for both the min and max settings and puts the two results in a clamp() that scales between screenMin and screenMax.
Why are text-xs and text-sm smaller than base?
They use negative steps (-2 and -1). A negative step divides by the ratio instead of multiplying, so the text gets smaller than base.
Should ratioMin and ratioMax be the same? Usually not. We set them to the same value only to make the math easier to follow. In a real project, use a bigger ratioMax so headings stand out more on desktop, and a smaller ratioMin so they fit on mobile.
Can I use fluid sizes on only some classes?
Yes. Set the prefix option. Only classes with the prefix use fluid sizes, and the regular text-* classes keep Tailwind's defaults.
How do I reuse heading sizes without adding classes to every element?
In your CSS, write a rule like h1, .h1 { @apply text-8xl; }. All H1 tags get the size, and you can add the h1 class to any other element to give it the same look.
Get Winden → dplugins.com