bold-lock

Bold on hover.
Zero layout shift.

npm ↗
GitHub ↗
TypeScript·Canvas measurement·React + Vanilla JS

Every browser will reflow text when you hover to bold — words push down, lines shift. Bold Lock measures the exact width difference using Canvas, then compensates with letter-spacing so the line never moves.

Live demo — hover the paragraph

Normal weight300
Hover weight700
Duration (ms)150

Hover over this paragraph to feel the weight change. The font grows heavier as your cursor moves over the text — but look carefully: the line endings stay exactly where they are. No word wraps to the next line. No layout shifts. The trick is measuring the width difference between the two weights using Canvas, then compensating with letter-spacing so the total advance width stays constant. Bold text normally pushes words around. This doesn't.

Move your cursor over the paragraph. Line endings stay fixed.

The problem with bold hover

Why text reflows

Bold glyphs are wider. When you change font-weight on hover, every character in the element grows slightly, words push into the next line, and the whole paragraph reflts. It's jarring and there's no CSS fix.

How we fix it

Canvas measureText gives us the exact advance width of each line at both weights. The difference becomes a negative letter-spacing compensation applied on hover, so total line width stays identical. One measurement pass on mount, zero reflow on hover.

Usage

Drop-in component

import { BoldLockText } from '@liiift-studio/bold-lock'

<BoldLockText normalWeight={300} hoverWeight={700} transitionDuration={150}>
  Hover over this text...
</BoldLockText>

Hook

import { useBoldLock } from '@liiift-studio/bold-lock'

const ref = useBoldLock({ normalWeight: 300, hoverWeight: 700 })
<p ref={ref}>{children}</p>

Options

OptionDefaultDescription
normalWeightcomputedFont weight at rest.
hoverWeight700Font weight on hover.
transitionDuration150Transition duration in milliseconds.
mode'element''element' = whole element hovers together, 'word' = individual word hover.