There are a number of ways to go about putting some text in a container and having it size itself to fill that container. There are different technologies we can use and different considerations to think about. Let us count the ways.
Magic Number it with viewport units
If you set type with vw
(viewport width) units, you can find an exact number where the text pretty closely fits the container and doesn’t break as you resize. I’d call this a magic number.
In this case, font-size: 25.5vw;
works down to a 320px viewport, but still will break much lower than that.
See the Pen Fitted Text with Viewport Units by Chris Coyier (@chriscoyier) on CodePen.
This is kind of a less exotic version of fluid typography, which involves more of a sprinkling of viewport units and min/max sizes.
FitText
Dave Rupert’s FitText is up for the job. You still need a bit of a magic number to get the sizing just right for any particular job:
See the Pen Fitted Text with FitText by Chris Coyier (@chriscoyier) on CodePen.
FitText without jQuery
If you aren’t using jQuery, there are options. Listed from the repo:
- non-jQuery FitText from @adactio
- Angular.js FitText.js from @patrickmarabeas
- AMP-HTML FitText
- FitText UMD by @peacechen
Example of the first:
See the Pen Fitted Text with FitText (no jQuery) by Chris Coyier (@chriscoyier) on CodePen.
textFit
Swap the words in FitText around and you got yourself textFit! It’s another JavaScript library that adjusts font sizes to fit text into a container. Big caveat here though: textFit is designed for two-dimensions. So you need a width
and height
on the element for it to do it’s thing.
See the Pen Fitted Text with textFit by Chris Coyier (@chriscoyier) on CodePen.
fitty
fitty is more like FitText in that it resizes type to maximize just horizontally, but actually seems to require no magic numbers.
See the Pen Fitted Text with fitty by Chris Coyier (@chriscoyier) on CodePen.
TextFill
TextFill is jQuery-based and requires a width, height, and a configured maximum font size to work. Here’s the basic demo we’ve been working from:
See the Pen Fitted Text with TextFill by Chris Coyier (@chriscoyier) on CodePen.
FlowType
FlowType is kind of designed to work on a whole document of text, resizing it all fluidly at once, with minimum and maxium viewport sizes. But you can scope it however you want. You also apply a magic number to get things how you want them.
See the Pen Fitted Text with FlowType by Chris Coyier (@chriscoyier) on CodePen.
Just use SVG
With width: 100%
and a viewBox
, SVG will be a fullsize box that resizes with an aspect ratio. Pretty neat trick! To set the type, you’ll need some magic numbers to get that viewBox
just right and push the text into the right spot — but it’s doable with zero dependencies, just like the viewport units demo.
See the Pen Fitted Text with SVG by Chris Coyier (@chriscoyier) on CodePen.
PSA: vw is broken, because it measures what is every single time the wrong thing. It measures the viewport’s initial containing block, which means the entire viewport width including the vertical scrollbar that is almost certain to be there. This matters on operating systems that don’t use overlay scrollbars (Windows, many Linuxes, and some macOS users opt out of overlay scrollbars); on Windows, it’ll generally amount to 100vw actually being 17px wider than the body width.
Therefore I say, if you are trying to measure things precisely with vw: (a) just don’t, you can’t succeed; and (b) if you insist on it anyway, make sure to allow at least 20px of slack (if that’s not acceptable, vw will not solve your problem)—and be ready to accept that even then your calc(100vw – 20px) may be wider than the body width in some circumstances.
Good to know.
I find when I’m using viewport units I’m often not looking for super precision. I often use them to sprinking in a little viewport related bumps up and down with calc.
The best way I’ve gone about solving this is creating a CSS variable
--window-width
and set it to100vw
. Then in javascript i set this CSS variable todocument.body.clientWidth
which will get the width of window without the scrollbar.Any suggestions on how to fit text vertically? I always end up with space above and below that I can’t seem to get rid of without adjusting line-height with magic numbers
Do you want to stretch the text wrt vertical height or align it?
To stretch it and keep the width proportional
Only the SVG worked properly in Firefox, none of the others.
Neither textFit or TextFill work in Chrome or Firefox.
fitty seemed to only react after screen resize event “ended”, but not live. (by design?)
All of these feel like the incredibly awful Flash based text of 10 years ago, except for pure CSS using vw (why call this a “magic” number when it’s simple math/calc going on… nothing magic, and makes total sense) The Flash criticism is a bit funny to me because it really was just a clumsy SVG, but SVG is just an “image”, which I can get behind for custom uses.
I agree that trying to make any adjustments with text “exact” is a recipe for disaster and reminds me of print designers making entire page layouts, with text, all as one image because they hated how they couldn’t control the design perfectly.
Let go of control, and either style with breakpoints, vw + calc (or whatever) and let go of perfection. You get better designs and less stress. If you need pixel prefect layout, SVG to the rescue. CSS shouldn’t have to fill every niche need, it’s pulling more than it’s weight already.
What is everyone’s opinion on this?
font-size: calc( 12px + (24 – 12) * ( (100vw – 400px) / ( 800 – 400) ));
Where the 12 is the minimum font-size, the 24 is the maximum font-size, the 400 is the min viewport width and the 800 is the max viewport width. As explained in this article: https://www.chenhuijing.com/blog/math-and-front-end/#%F0%9F%8E%B9
I do it using JS, see eg https://tobireif.com/demos/ → resize while viewing the heading.
The code: view source → “Heading Size”.
Pierre Darrieutort wrote in to share their library that is related to all this: Fitext.