This is part guide and part experiment. We'll explore how container queries, the CSS clamp function, and CSS grid, can be combined to create a range of fluid text styles, which are enhanced with a container query.
It's a familiar sight, text in boxes, spanning columns. What's different about this example is that I haven't used media queries to change font sizes, and the same code is used for each individual box of text, regardless of how wide it is, spooky.
The typical approach
Typically, you'd use a combination of media queries and fluid typography to achieve what's happening in the example, e.g.
The example doesn't give any control over what happens with the boxes that don't span the full 12 columns, so you'd also use modifier classes specifically for those cases, e.g.
Or this kind of utility-based approach:
I like how the code can be defined in blocks, but it becomes repetitive, that's due to the use of media queries.
What compounds things is that there's a similar approach with spacing units and every other part of the system, so what you're seeing here is the tip of the iceberg.
Syncing all elements of a design system with every media query is a drain on time.
Text may appear too small on some screens and too large on others.
Let's try another approach.
Using container queries
Define some static font sizes as custom properties
(I always use
rem units for accessibility),
so we can re-use them, I usually add them after any CSS resets.
These values usually come from a design system or a figma file, or you can make up your own.
Create a class, I called it
.content for obvious reasons,
then select the elements you want to apply the responsive font-sizes to.
- I added
container-type: inline-size;to the parent element.
- I then selected elements I want to apply styles to, they have to be children of the container, inb this case it's
- Finally, I used a
@containerquery to use the
cqwunit, unless you're within a container this has no effect, it let's you get the size of the container and size the text dynamically based on the width of it.
Always test the effectiveness of using
cqw units for
font-size by zooming (using ctrl + / -). They can cause accessibility failures.
I found using unitless values, e.g.
the most sensible way
line-height with fluid & responsive typography.
Unitless values are multipliers,
if you have
line-height: 1.5 the computed value of
line-height will be
The way I do this is not an exact science (no, I'm not using a graph), and usually "by-eye", so the mid-range values I've used are based on what feels right.
Once you implement that code, to see it take effect, you'll need to change the widths of the containers.
Add containers to a grid
Drop the containers onto a CSS grid, you don't need anything fancy, this kind of thing will do the trick:
Then, write CSS that places the containers within the columns you want them to appear in. For my example, I created several utility classes.
You might be thinking, hang-on we're using media queries again; either way, we still need a way to lay out the containers on a grid, use whatever method works best.
For a bit of variety with the headings, we can create utility classes.
We don't need to touch the paragraphs again as the initial
.box class has container queries that handle that.
To apply fluid spacing between the paragraphs and headings,
we can tap into the
cqw unit again,
to apply spacing proportionate to the size of the text in each container.
The min and max values could also come from a series of custom properties from a design system.
I'm loosely adhering to a design system, this is intentional,
I don't think
we should get too hung up on absolute perfection with intermediary font-sizes using
but we definitely don't want any irregularities,
just use the static values and go with what feels right in-between.
We've looked at how a typical setup for fluid and responsive typography would typically work, and then seen an alternative, which I prefer, you might too (if you do, I'd love to hear from you).
rem units to avoid user zoom accessibility issues,
zoom in to test your solution using the browser to make sure.
If you have any suggestions as to how the examples can be made clearer, easier to understand, or how I can add any missing use-cases you feel would help others, I'd love nothing more than to hear from you! Reach out to me on Twitter, or shoot me an email.
Written by Morgan Feeney
I’ve been designing and developing for almost 2 decades.
Read about me, and my work.
For juicy tips and exclusive content, subscribe to my FREE newsletter.