text-to-fit sizing
CSS can’t scale a font to fill a container — font-size doesn’t know where to stop. Fit Flush binary-searches the right size to within half a pixel, with variable-font safety built in.
Live demo — drag the sliders
Variable fonts — animate the weight after the fit
How it works
CSS can’t fit a font size
There’s no CSS property that says “make this text as large as it can be while staying inside its container.” clamp() just rescales, and vw units don’t know about your layout. You need measurement.
About a dozen measurements
Fit Flush probes a hidden clone of the element — try a size, measure, narrow the range. In height and both modes it binary-searches to within 0.5 px in about 12 measurements; a single line in width mode is predicted from one measurement and checked, usually 3 in all. Nothing visible moves until the final size is written.
Variable-font safe
Pass vfSettings with your axis ranges and Fit Flush measures with every axis at its max, so the size still fits when an animation drives the axis there. An optical-size axis is widest at its minimum: give min too and both ends are checked.
Resize-aware, font-load-aware
The live API fits straight away, then refits when the container resizes (a ResizeObserver), when the text changes, and when web fonts finish loading (document.fonts.ready), so a size measured with the fallback font is replaced.
Usage
TypeScript + React · Vanilla JS
Drop-in component
import { FitFlushText } from '@overpunch/fit-flush/react'
<FitFlushText mode="width">
Display Headline
</FitFlushText>Hook — attach to any element
import { useFitFlush } from '@overpunch/fit-flush/react'
const { ref } = useFitFlush({ mode: 'both' })
<h1 ref={ref}>Display Headline</h1>Vanilla JS — one-shot
import { fitFlush } from '@overpunch/fit-flush'
const el = document.querySelector('h1')
fitFlush(el, { mode: 'width', min: 12, max: 400 })
// Undo it: restores the original inline styles
// removeFitFlush(el)Vanilla JS — live (refits on resize, text change and font load)
import { fitFlushLive } from '@overpunch/fit-flush'
const handle = fitFlushLive(el, {
mode: 'both',
// Variable font safety — measure at each axis' widest end
vfSettings: { wdth: { max: 125 }, wght: { max: 900 } },
})
// Later:
handle.refit() // force re-measurement
handle.dispose() // restore original fontSize, whiteSpace, and --ff-sizeOptions
| Option | Default | Description |
|---|---|---|
| mode | 'both' | Which dimension to fill: 'width' (one line), 'height', or 'both'. Height and both need a container with a height of its own. |
| min | 8 | Minimum font-size in px. |
| max | 400 | Maximum font-size in px. |
| precision | 0.5 | Convergence tolerance in px — binary search stops within this gap. |
| padding | 0 | Inset from container edges in px. Number = all sides; { x, y } = per-axis. |
| vfSettings | — | Variable-font axis ranges, e.g. { wght: { max: 900 } }. Measurement uses each axis at its max (and at its min, where given) for worst-case safety. |
| container | parentElement | Override the container element used for dimension measurement. |
| onFit | — | Callback fired after each fit that wrote a size, receiving the resolved font-size in px. |
no-code
Use it in Webflow, Framer & Figma
The same effect, no build step — drop it straight into your design tool.
Webflow
One script tag, then mark any element with data-fitflush. Configure it with data-* attributes.
<!-- Site Settings → Custom Code → Footer, or an Embed element -->
<script src="https://cdn.jsdelivr.net/npm/@overpunch/fit-flush/dist/fitflush.webflow.min.js"></script>
<!-- Then add data-fitflush to any text element -->
<h1 data-fitflush>Your headline</h1>Framer
Insert → Code → New Component, then paste FitFlush.tsx ↗. It imports the core from esm.sh and exposes every option in the property panel — no build step.
import { /* core */ } from "https://esm.sh/@overpunch/fit-flush"Figma · beta
Part of the Type Tools Figma plugin ↗ — Plugins → Development → Import plugin from manifest, run Type Tools, and pick this tool. Here it works with compromises — tracking or named-instance swaps (Figma can't set variable axes).