Basic usage
<!-- Basic usage -->
<script setup>
import NumberFlow from '@number-flow/vue'
</script>
<template>
<NumberFlow :value="123" />
</template>
<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.
<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
<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
trend: boolean'increasing''decreasing'
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.
continuous: boolean
If set, number transitions will appear to pass through in-between numbers. Has no effect if trend
is false
.
animated: boolean
Can be set to false
to disable all animations and finish any current ones.
See the
willChange: boolean
If set, NumberFlow applies will-change
properties
- 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:
respectMotionPreference: boolean
Can be set to false
to animate regardless of the user’s reduced motion preference.
Emits
animationsstart: (e: CustomEvent) => void
Triggered when update animations start.
Not to be confused with the built-in
animationstart
event<NumberFlow>
element itself.
animationsfinish: (e: CustomEvent) => void
Triggered when update animations finish.
Styling
There’s some CSS properties you can use to style the component:
--number-flow-mask-[height|width]: <length>
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>
Sets the height of each character. This can be used to adjust the vertical spacing between numbers.
font-variant-numeric: tabular-nums
Ensures all numbers are the same width, which can prevent digits from shifting during transitions.
See
Grouping
If you’re using multiple <NumberFlow>
components on one line, you can wrap
them in a <NumberFlowGroup>
to properly sync their transitions:
<script setup lang="ts">
import NumberFlow, { NumberFlowGroup } from '@number-flow/vue'
const { value, diff } = defineProps<{
value: number
diff: number
}>()
</script>
<template>
<NumberFlowGroup>
<div style="--number-flow-char-height: 0.85em" class="flex items-center gap-4 font-semibold">
<NumberFlow :value :format="{ style: 'currency', currency: 'USD' }" class="~text-2xl/4xl" />
<NumberFlow
:value="diff"
:format="{ style: 'percent', maximumFractionDigits: 2, signDisplay: 'always' }"
:class="[
'~text-lg/2xl transition-colors duration-300',
diff < 0 ? 'text-red-500' : 'text-emerald-500'
]"
/>
</div>
</NumberFlowGroup>
</template>
<NumberFlowGroup>
doesn’t render an element or accept any props.
Composables
useCanAnimate(opts?: { respectMotionPreference?: MaybeRefOrGetter<boolean> }): ComputedRef<boolean>
Returns a computed ref whose value is true
if NumerFlow can animate, i.e. the browser supports the
Limitations
andScientific notations aren’t supported.engineering - Selected text inside the number will not respect color changes from
::selection
, if any. - Backgrounds and borders on
<NumberFlow>
won’t scale smoothly during transitions.