NumberFlow

 for 
43,110

A component to transition, format, and localize numbers. Dependency-free. Accessible. Customizable.

Basic usage

<!-- Basic usage -->
<script>
import NumberFlow from '@number-flow/svelte'
</script>

<NumberFlow value={123} />

<NumberFlow> will automatically transition when the value prop changes.


Props

format: Intl.NumberFormatOptions

The format options passed to the internal Intl.NumberFormat instance.

<NumberFlow format={{ notation: 'compact' }} {value} />

locales: Intl.LocalesArgument

The locales passed to the internal Intl.NumberFormat instance.

prefix: string, suffix: string

A custom prefix or suffix for the number.

$3/moClick anywhere to change numbers
<NumberFlow
	{value}
	format={{ style: 'currency', currency: 'USD', trailingZeroDisplay: 'stripIfInteger' }}
	suffix="/mo"
/>

Timings

There are three props to customize the animation timings. Each accept an EffectTiming object:

124.23Click anywhere to change numbers
<NumberFlow
	transformTiming={{
		// Used for layout-related transforms:
		duration: 750, easing: 'linear(0,0.008,0.028,0.06,0.099,0.145,0.196,0.249,0.304,0.36,0.416,0.47,0.523,0.573,0.621,0.667,0.709,0.748,0.784,0.817,0.847,0.874,0.898,0.92,0.939,0.955,0.97,0.982,0.992,1.001,1.008,1.014,1.019,1.022,1.025,1.027,1.028,1.028,1.028,1.028,1.027,1.026,1.025,1.024,1.022,1.02,1.019,1.017,1.016,1.014,1.013,1.011,1.01,1.009,1.008,1.007,1.006,1.005,1.004,1.003,1.003,1.002,1.001,1.001,1.001,1,1,1,1,1,0.999,0.999,0.999,0.999,1)'
	}}
	spinTiming={{
		// Used for the digit spin animations.
		// Will fall back to `transformTiming` if unset:
		duration: 750, easing: 'linear(0,0.008,0.028,0.06,0.099,0.145,0.196,0.249,0.304,0.36,0.416,0.47,0.523,0.573,0.621,0.667,0.709,0.748,0.784,0.817,0.847,0.874,0.898,0.92,0.939,0.955,0.97,0.982,0.992,1.001,1.008,1.014,1.019,1.022,1.025,1.027,1.028,1.028,1.028,1.028,1.027,1.026,1.025,1.024,1.022,1.02,1.019,1.017,1.016,1.014,1.013,1.011,1.01,1.009,1.008,1.007,1.006,1.005,1.004,1.003,1.003,1.002,1.001,1.001,1.001,1,1,1,1,1,0.999,0.999,0.999,0.999,1)'
	}}
	opacityTiming={{
		// Used for fading in/out characters:
		duration: 350, easing: 'ease-out'
	}}
/>

For spring-based easings, I’d recommend Kevin Grajeda’s generator or easing.dev.

trend: boolean'increasing''decreasing'Default: true

Controls the direction of the digits.

  • true: The digits go up if the number increases, and down if the number decreases.
  • false: Ignores the trend of the number; each digit goes up if it increases and down if it decreases. This can be useful if you want to animate number changes without conveying an overall increase or decrease (example).
  • "increasing": The digits always go up.
  • "decreasing": The digits always go down.
20Click anywhere to change numbers

continuous: booleanDefault: false

If set, number transitions will appear to pass through in-between numbers. Has no effect if trend is false.

120
Click anywhere to change numbers

animated: booleanDefault: true

Can be set to false to disable all animations and finish any current ones. See the input example for a usage scenario.

willChange: booleanDefault: false

If set, NumberFlow applies will-change properties to relevant elements. This can be useful if:

  • Your number is guaranteed to change frequently
  • You experience text misalignment when a transition completes

Note that “excessive use of will-change will result in excessive memory use” (source: MDN).

respectMotionPreference: booleanDefault: true

Can be set to false to animate regardless of the user’s reduced motion preference.


Events

animationsstart: (e: CustomEvent) => void

Triggered when update animations start.

animationsfinish: (e: CustomEvent) => void

Triggered when update animations finish.


Styling

NumberFlow uses a custom element under the hood, and exposes parts for styling purposes:

$3/moClick anywhere to change numbers

You can use your browser’s inspector to see which part attributes are available to style. Note that changing the font-size of digits is difficult due to the CSS techniques NumberFlow uses.

::part styles may cause a flash of unstyled content in old browsers.

See workaround You can use feature detection to apply ::part styles only to browsers that support Declarative Shadow DOM (DSD). Add the following snippet to your <head>:

<script>
	if (
		HTMLTemplateElement.prototype.hasOwnProperty('shadowRootMode') ||
		HTMLTemplateElement.prototype.hasOwnProperty('shadowRoot') // old Chrome/Edge
	)
		document.documentElement.setAttribute('data-supports-dsd', '')
</script>

Then ensure your ::part styles use it:

:root[data-supports-dsd] number-flow-svelte::part(suffix) {
}

If you’re using Tailwind, you can do this with a custom variant:

// tailwind.config.js
import plugin from 'tailwindcss/plugin'

export default {
	// ...
	plugins: [
		plugin(({ matchVariant }) => {
			matchVariant('part', (p) => `:root[data-supports-dsd] &::part(${p})`)
		})
	]
}
<NumberFlow class="part-[suffix]:text-muted" />

There’s also some CSS properties you can use to style the component:

--number-flow-mask-[height|width]: <length>Default: .25em | .5em

These adjust the height and width of the gradient fade-out masks at the edges of the number. --number-flow-mask-height also gets used as the top and bottom padding for the number.

--number-flow-char-height: <length>Default: 1em

Sets the height of each character. This can be used to adjust the spacing between digits during spin animations.

font-variant-numeric: tabular-nums

Ensures all numbers are the same width, which can prevent digits from shifting during transitions. See MDN for more information.


Grouping

If you’re using multiple <NumberFlow> components on one line, you can wrap them in a <NumberFlowGroup> to properly sync their transitions:

$124.23 +5.64%
Click anywhere to change numbers

<NumberFlowGroup> doesn’t render an element or accept any props.


Stores

getCanAnimate(opts?: { respectMotionPreference?: boolean }): Readable<boolean>

Returns a readable store whose value is true if NumerFlow can animate, i.e. the browser supports the required features and (optionally) the user is okay with motion.


Limitations

  • Scientific and engineering notations aren’t supported.
  • Backgrounds and borders on <NumberFlow> won’t scale smoothly during transitions.