@typefit/react
v1.0.0
Published
React APIs to make text always fit perfectly.
Readme
@typefit/react
React bindings for Typefit.
Install this package in React apps. It includes a small polymorphic component, a hook, and all
public Typefit types re-exported from @typefit/core.
Install
bun add @typefit/reactnpm install @typefit/react@typefit/react depends on @typefit/core, so you won't need to install the core package
separately.
Component
import { Typefit } from '@typefit/react';
export function Hero() {
return (
<Typefit as="h1" maxSize={96} lines={{ min: 2 }} hideUntilFit>
Text that always fits perfectly.
</Typefit>
);
}Typefit is polymorphic through the as prop and forwards regular element props such as
className, style, id, and event handlers.
<Typefit
as="h2"
className="font-semibold tracking-tight text-neutral-950"
maxSize={80}
lines={{ target: 2, max: 3 }}
>
Styled with normal React props.
</Typefit>Hook
Use useTypefit when you need direct access to the result or a manual refresh.
import { useTypefit } from '@typefit/react';
export function MeasuredHeadline() {
const { ref, result, refresh } = useTypefit<HTMLHeadingElement>({
maxSize: 96,
lines: { target: 2 },
});
return (
<>
<h1 ref={ref}>Measured with a hook.</h1>
<button type="button" onClick={refresh}>
Refresh
</button>
<output>{result?.fontSize.toFixed(1)}px</output>
</>
);
}Custom Fonts
Use CSS normally:
@font-face {
font-family: "Open Runde";
src: url("/fonts/OpenRunde-Semibold.woff2") format("woff2");
font-weight: 600;
font-style: normal;
font-display: swap;
}
.headline {
font-family: "Open Runde", system-ui, sans-serif;
font-weight: 600;
line-height: 1.05;
}<Typefit as="h1" className="headline" hideUntilFit>
Custom font from CSS.
</Typefit>For stricter measurement control, pass a font callback:
const headlineFont = (size: number) =>
`600 ${size}px "Open Runde", system-ui, -apple-system, sans-serif`;
<Typefit as="h1" font={headlineFont} maxSize={112}>
Explicit custom font.
</Typefit>;Typefit listens for browser font-loading events, clears cached metrics, and refits observed instances after the real font is ready.
Common Props
| Prop | Default | Description |
| --- | --- | --- |
| as | 'span' | Element rendered by the component. |
| hideUntilFit | false | Hide until the first measurement completes. |
| disabled | false | Skip fitting. |
| onFit | none | Called with (result, element) after fitting. |
| minSize | 10 | Smallest font size Typefit may choose. |
| maxSize | 512 | Largest font size Typefit may choose. |
| lines | none | { min, target, max } line-count policy. |
| strategy | 'balance' | 'balance' or 'fill'. |
| balance | { mode: 'even' } | Wrap scoring options. |
| shape | none | Shape preset or custom rows. |
| snap | none | Allowed font sizes. |
| avoidWidows | false | Avoid short final lines when possible. |
| observe | true | Refit on resize, content changes, and font loads. |
All core fitting options are supported.
Shape Example
<Typefit
as="h1"
maxSize={96}
lines={{ min: 3 }}
shape="diamond"
balance={{ mode: 'even' }}
>
Widest in the middle.
</Typefit>Snap Example
<Typefit snap={[24, 32, 40, 48, 56, 64, 72, 88, 104, 120]}>
Fit to a type scale.
</Typefit>Browser Support
@typefit/react works in any current browser supported by React and Typefit. The underlying
@typefit/core measurement uses OffscreenCanvas when available and falls back to a DOM canvas
context, so Chromium, Firefox, WebKit/Safari, and other standards-compliant browsers are supported.
The component and hook also listen for resize, mutation, and browser font-loading events when
observe is enabled.
Contributing
We would love to have your help in making Typefit better.
Here's how you can contribute:
- Report a bug you found while using Typefit
- Request a feature that you think would be useful
- Submit a pull request if you want to contribute with new features or bug fixes
License
Typefit is licensed under the MIT License.
