FitText.js as a React v16+ component.
If you want to make specific text fit within a container, and then maintain that ratio across screen sizes, this component is for you.
FitText is a particularly useful approach for:
- Predetermined content (ie. not user generated or dynamic)
- Text that fits within a container until it hits a minimum or maximum font size, and then reflows normally from there
- Multi-line text that fits
If you don’t have any of these requirements, another approach might suit you better. Some possible alternatives include:
- Using a pre-made SVG without outlining the text, if you have predetermined content, and want truly the exact same layout across all viewports
- Using SVG dynamically with React FitterHappierText (the changes are all open as Pull Requests on Brent Jackson’s original)
- Using BigIdeasText within React lifecycle hooks like
componentDidMount()
. I may open source a React-specific fork of Zach Leatherman’s original in the future. - Using Mike Riethmuller’s clever CSS-only fluid type technique and other examples, if you have some scaling constraints but aren’t concerned about reflow across all sizes
- Plain viewport units, if the only relevant container is the width (or height) of the page:
<div class="example">
Scale with the viewport
</div>
/* Minimum font size */
.example {
font-size: 24px;
}
/* Scale linearly after this breakpoint */
@media (min-width: 480px) {
.example {
font-size: 5vw;
}
}
If you’re curious why some sort of automatic scaling isn’t already possible using CSS alone, or why it might still be a challenge in the future, read more in this CSS Working Group drafts issue.
This component is written specifically for React v16 and up, includes tests, and uses state to avoid DOM manipulation.
The existing React FitText component by @gianu should still work with current versions of React, and is stateless, but manipulates the DOM directly to change font sizes.
The approach I’m using feels more React-appropriate, at least to me. I use this component regularly enough that it made sense for me to maintain my own version regardless.
npm install --save @kennethormandy/react-fittext
import FitText from '@kennethormandy/react-fittext'
<FitText compressor={0.5}>The quick brown fox jumps over the lazy dog.</FitText>
With multiple children:
<FitText compressor={0.5}>
<React.Fragment>
<h2>Pangram</h2>
<p>The quick brown fox jumps over the lazy dog</p>
</React.Fragment>
</FitText>
From the original FitText.js documentation:
If your text is resizing poorly, you'll want to turn tweak up/down “The Compressor.” It works a little like a guitar amp. The default is
1
. —davatron5000
<FitText compressor={3}>The quick brown fox jumps over the lazy dog.</FitText>
<FitText compressor={1}>The quick brown fox jumps over the lazy dog.</FitText>
<FitText compressor={0.3}>The quick brown fox jumps over the lazy dog.</FitText>
<FitText compressor={0.5} minFontSize={24} maxFontSize={96}>
The quick brown fox jumps over the lazy dog.
</FitText>
Change the included debounce resize timeout. How long should React FitText wait before recalculating the fontSize
?
<FitText debounce={3000} compressor={0.5}>
The very slow brown fox
</FitText>
The default is 100
milliseconds.
React FitText needs the viewport size to determine the size the type, but you might want to provide an explicit fallback when using server-side rendering with React.
<FitText defaultFontSize={100} compressor={0.5}>
The quick brown fox
</FitText>
The default is inherit
, so typically you will already have a resonable fallback without using this prop, using CSS only. For example:
.headline {
font-size: 6.25rem;
}
<div className="headline">
<FitText compressor={0.5}>The quick brown fox</FitText>
</div>
Add the vertical
prop to scale vertically, rather than horizontally (the default).
<div style={{ height: '75vh' }}>
<FitText vertical compressor={1.25}>
<ul>
<li>Waterfront</li>
<li>Vancouver City Centre</li>
<li>Yaletown–Roundhouse</li>
<li>Olympic Village</li>
<li>Broadway–City Hall</li>
<li>King Edward</li>
<li>Oakridge–41st Avenue</li>
<li>Langara–49th Avenue</li>
<li>Marine Drive</li>
</ul>
</FitText>
</div>
Use a different parent, other than the immediate parentNode
, to calculate the vertical height.
<div id="js-example">
<AnotherThing>
<FitText vertical parent="js-example">
{dynamicChildren}
</FitText>
</AnotherThing>
</div>
<div>
<div style={{ height: '1000px' }} ref={el => (this.parentNode = el)}>
<h1>A contrived example!</h1>
</div>
<FitText vertical parent={this.parentNode}>
{dynamicChildren}
</FitText>
</div>
git clone https://github.com/kennethormandy/react-fittext
cd kennethormandy
# Install dependencies
npm install
# Run the project
npm start
Now, you can open http://localhost:8080
and modify src/dev.js
while working on the project.
To run the Storybook stories instead:
npm run storybook
I’ve used various versions of this project in the following type specimen sites:
- Regina Black
- DDC Hardware
- Google Fonts + Japanese collection
- Boomville
- Tofino v2
- My website
- Protipo
- TBA
- TBA
Other projects:
- Cygnus Design Group (added vertical support)
- Your project? Add it to the README
- The original FitText.js by @davatron5000
- react-fittext by @gianu
Copyright © 2014 Sergio Rafael Gianazza
Copyright © 2017–2019 Kenneth Ormandy Inc.