All we need for this tutorial is a little HTML page and a CSS file. Go ahead and create the following files:
index.html
global.css
Now, inside index.html, add the following:
`
Fluid type demo
Fusce dapibus, tellus ac cursus commodo
Donec ullamcorper nulla non
Morbi leo risus, porta ac consectetur
Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Donec sed odio dui. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Vestibulum id ligula porta felis euismod semper.
`
That’s it for HTML. It’s some lipsum placeholder text to demonstrate our fluid type system. Job done!
That’ll make things look a little nicer. We’re using my favourite font, Georgia, as our base and the system font stack for headings. This contrast will really help you see the fluid type in action.
Now we can add the smart stuff—the fluid type setup. Open up global.css and add the following to it:
There’s a lot going on here, so let’s break it down.
The clamp() function takes a minimum value, an ideal value and a maximum value. This allows us to create some locks.
To power all of this, we’re using 3 custom properties:
--fluid-type-min is the smallest we will allow our text to go
--fluid-type-target is our ideal, fluid setting. We use calc() because if you just use a viewport unit to size your type, it can cause problems in zooming, which in turn, creates a WCAG accessibility failure.
--fluid-type-max is the largest we will allow our text to go
For all three custom properties, we are setting the default value as the second parameter. This means that you can drop this fluid type system into any project, and even if none of those properties are defined: the system will still work off those default, sensible values.
We have applied our fluid type system to the following elements: h1, h2, h3, p. We could—if we wanted—turn this into a utility class for maximum portability. For this tutorial, we’ll keep it simple with type selectors though.
We want to add some specific settings for each of these, using custom properties, or all the text will be the same size.
For the <h1>, we increase the --fluid-type-target to a larger, 5vw. By increasing the viewport unit, we speed up the rate of growth, which will help to maintain its extra large size. To reduce the rate of growth and have less difference between your minimum and maximum sizes: reduce the size of --fluid-type-target.
For all of the other elements, the default growth rate is fine, so all we’re doing is setting sensible minimum and maximum sizes, using standard rem units.
This is a very simple, bare-bones system and will comfortably support a lot of usecases. For more advanced, complex designs, I would recommend using something like Typetura which gives very fine control or Utopia, which is a level up from this approach that we’ve learned today.
For full disclosure, I’m not a huge fan of fluid type, personally. I’ve had such a mixed, checkered history with it over the years, and personally, I prefer to create a size scale, implemented via media queries. That’s what this site does, at the time of writing.
Fluid type is in demand, too, so what you’ve learned today will undoubtedly be useful at some point—if nothing else, to give you a useful context of how clamp() works.
Until next time, take it easy 👋
Big thanks to Eric Bailey for casting his expert eye on this for me.
Enjoyed this article?You can support us by leaving a tip via Open Collective