Bar Chart Race
Ranked bars reorder over time. Install with npx remotion-ui@latest add bar-chart-race.
PrimitiveData & mediaAdvanced
$ npx remotion-ui@latest add bar-chart-raceRanked bars that overtake each other as the clock runs.
import { BarChartRace } from "@/remotion/primitives/bar-chart-race";
<BarChartRace
series={[
{ label: "Studio", values: [42, 58, 66, 72, 78, 84] },
{ label: "Motion", values: [18, 34, 57, 76, 92, 108] },
]}
steps={["Q1", "Q2", "Q3", "Q4", "Q5", "Q6"]}
framesPerStep={18}
/>Data shape
Raw time series, one value per keyframe, interpolated at render — not
pre-computed rankings. framesPerStep sets how long the clock takes to travel
between two keyframes, so the whole race runs for framesPerStep × (steps − 1).
steps supplies the running caption.
Every series should carry the same number of values. A short one holds its last value rather than dropping off the board.
Why the overtakes look right
Rank is fractional, not an integer sort position: each series measures how far above it every other series sits, softened by a sigmoid. An integer rank makes bars teleport a full row the instant two values cross, which is exactly the moment the format exists to show. The softening width scales with the leader's value, so a crossover reads the same whether the chart counts in tens or in millions.
Where it sits
animated-bar-chart is the static counterpart — one fixed ranking revealed with
a value axis. Use that when the order never changes.
visibleRows bounds the board; series ranked below it fade out instead of
clipping, so dropping off reads as losing rather than as a render bug.
Rank is fractional, not an integer sort position: each series measures how far above it the others sit, softened by a sigmoid. Integer ranks make bars teleport a full row the instant two values cross — the exact moment the format exists to show. Takes raw time series and interpolates them, not pre-computed rankings.
Agent notes
Install first, then import the copied source component locally. AI guide →
@/remotion/primitives/bar-chart-race- Use when: data stories, metrics, charts, and numeric proof points.
- Customize: series, steps, framesPerStep, visibleRows, plus copied source for timing, layout, colors, and typography.
- Rule: do not import this component from the
remotion-uinpm package; it is copied into your project.
Usage
import { BarChartRace } from "@/remotion/primitives/bar-chart-race";
<BarChartRace
series={[
{ label: "Studio", values: [42, 58, 66, 72, 78, 84] },
{ label: "Motion", values: [18, 34, 57, 76, 92, 108] },
]}
steps={["Q1", "Q2", "Q3", "Q4", "Q5", "Q6"]}
framesPerStep={18}
/>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
| series | RaceSeries[] | required | One entry per contender: `{ label, values, color? }`, one value per keyframe. |
| steps | string[] | undefined | Keyframe captions, e.g. years. Shown as the running clock. |
| framesPerStep | number | 26 | Frames spent travelling between two keyframes. |
| visibleRows | number | 6 | How many rows stay on the board. Below that, series fade out. |
| width | number | 900 | Overall width, label column included. |
| rowHeight | number | 66 | Bar height. Type scales off it. |
| gap | number | 14 | Space between rows. |
| labelWidth | number | 200 | Width reserved for the row labels. |
| showStepLabel | boolean | true | Large step caption in the bottom-right corner. |
| valueFormatter | (value: number) => string | compact | Formats the figure inside each bar. |
| delayInFrames | number | 0 | Frames to wait before the clock starts. |
| exitAtInFrames | number | undefined | Frame the bars collapse on. Omit to hold the final standings. |
| frame | number | undefined | Frame override — pass the parent frame inside a `<Sequence>`. |