Skip to content
Open source · MIT · net8.0 / net9.0 / net10.0

Motion for Blazor,
written in C#.

Springs, gestures, keyframes, variants, drag, layout and exit animations, inspired by Framer Motion and rebuilt for Blazor. All of the maths runs in C#, none of the JavaScript wiring is yours, and no animation library ships alongside it.

dotnet add package Bit.Bmotion
Tile.razor
<Bmotion Initial="Bm.To(opacity: 0, y: 26, scale: 0.9)"
         Animate="Bm.To(opacity: 1, y: 0, scale: 1)"
         WhileHover="Bm.To(scale: 1.05, y: -6)"
         WhileTap="Bm.To(scale: 0.96)"
         Transition="Bm.Spring(stiffness: 220, damping: 20)">
    <a class="tile" href="springs">Springs</a>
</Bmotion>
Maths in C#springs, tweens, inertia, easing and colour interpolation
Compositor firstenter, exit, hover and variants run on the Web Animations API
No JavaScript to writethe small bridge imports itself on first use
Prerender friendlyenter animations play from the served HTML

Capabilities

What you can build with it

Every card links to the demo that proves it, and every demo ships its own source one click away.

Springs, tweens and inertia

Stiffness and damping, or bounce and duration if that is how you think - plus the full easings.net family, per property if you want.

Springs →

Gestures

WhileHover, WhileTap and WhileFocus overlay a state on the base animation and revert themselves. Tap is keyboard-accessible out of the box.

Gestures →

Variants

Name your states once, then switch a whole subtree to one of them and stagger the children into place - even from a per-element function.

Variants →

Keyframes

Sequences of values with their own offsets, per-segment easing and repeat behaviour, written as plain collection expressions.

Keyframes →

Split text

Headlines that assemble a character, a word or a line at a time - split in C#, so nothing re-splits on re-render and a screen reader still reads the sentence.

Split text →

AnimatePresence

Exit animations that run before the element actually leaves the DOM - for one element, a keyed list, or content being replaced.

AnimatePresence →

Drag and reorder

Axis locks, container constraints, elastic edges, momentum - and lists that reorder themselves under the pointer without re-rendering.

Drag →

Layout animations

FLIP the gap between two layouts, with border-radius correction and child counter-scaling handled for you.

Layout →

Scroll and viewport

Hand a scroll-linked animation to the browser's native scroll timelines - no handler, no interop - or scrub it yourself as a motion value, or trigger it the first time an element comes into view.

Scroll →

Programmatic control

Animate by selector, interpolate a bare number, build a timeline with overlapping steps, then pause it and change its speed.

Programmatic →

SVG and motion paths

Send an element along a path, draw a stroke on with pathLength, or morph one shape into another.

Motion path →

Accessibility and diagnostics

prefers-reduced-motion that softens rather than deletes, keyboard-accessible taps, and an inspector that shows what the engine is doing.

Accessibility →

In practice

See it in code

01

One component, two states

Initial is where the element starts, Animate is where it is going. Change Animate in your own state and the element animates there from wherever it currently is - there is nothing to start or stop.

Basics →
<Bmotion Initial="Bm.To(opacity: 0, y: 20)"
         Animate="@(_open ? Bm.To(opacity: 1, y: 0) : Bm.To(opacity: 0, y: 20))"
         Transition="Bm.Spring(bounce: 0.4, duration: 0.6)">
    <div>Hello, Bmotion!</div>
</Bmotion>
02

Name the states, stagger the children

Variants are named states declared once. A container switches its whole subtree to one of them, and its transition's staggerChildren brings the children in one after another.

Variants →
<Bmotion Variants="_list" InitialState="hidden"
         State='@(_open ? "visible" : "hidden")'
         Transition="Bm.Tween(staggerChildren: 0.08, delayChildren: 0.2)">
    <ul>
        <Bmotion Variants="_item"><li>Item 1</li></Bmotion>
        <Bmotion Variants="_item"><li>Item 2</li></Bmotion>
    </ul>
</Bmotion>
03

Animate out before Blazor removes it

An element that has left the DOM cannot animate. BmotionAnimatePresence keeps removed content rendered until its Exit has played - you still just flip a bool.

AnimatePresence →
<BmotionAnimatePresence IsPresent="@_show" Mode="BmPresenceMode.Wait">
    <Bmotion Initial="Bm.To(opacity: 0)"
             Animate="Bm.To(opacity: 1)"
             Exit="Bm.To(opacity: 0)">
        <div>I animate in and out!</div>
    </Bmotion>
</BmotionAnimatePresence>

Comparison

Why not wrap a JavaScript animation library?

A wrapper drives the DOM from a second engine behind Blazor's back, and every value it needs has to cross the interop boundary. Bmotion keeps the engine in C#, next to the state it animates.

ConcernJavaScript library + interopBmotion
Where the maths runsIn the browser's JavaScript engineIn C# - springs, tweens, inertia, easing, colours and transforms
What you writeElement ids, option objects and interop glueRazor parameters: Initial, Animate, WhileHover, Exit...
Exit animationsHand-timed removal after the animation endsPresence components hold the element until its exit has played
Cheap animationsUp to the libraryPre-sampled in C# and handed to the Web Animations API - no per-frame interop
PrerenderingNothing moves until the script runsBmPrerenderMode.Animate plays enter animations in CSS from the served HTML
Script to shipThe library plus its wrapperOne small module, imported on demand

Where to start

Choose your path

New to Bmotion?

Install the package, register one service and animate your first element in five minutes.

Getting started →

Want to see it move?

A page of live samples for every feature - hover, press, drag and scroll them, each with its source.

Open the demos →

Building with an AI agent?

This site is an MCP server: point your agent at /mcp and it measures a spring on the real engine instead of guessing.

Try the MCP server →

Questions

Frequently asked

Is this Framer Motion running through JavaScript interop?

No. It is inspired by Motion (Framer Motion) and keeps its vocabulary, but the engine - springs, tweens, inertia, keyframes, easing, colour interpolation, gesture state and transform composition - is C#. JavaScript is used only as a thin bridge to browser APIs, and it imports itself the first time an animation runs.

Which render modes does it work in?

Blazor WebAssembly is fully supported. On Blazor Server the compositor path works, so enter, exit, hover, tap and variant animations on transform and opacity play normally; features that need the per-frame loop - inertia, colour and dimension interpolation - become instant changes. It targets .NET 8, 9 and 10.

What happens while the page is still prerendered?

By default an element is served at its Initial state and animates once the runtime is interactive. BmPrerenderMode.Final serves it at rest, and BmPrerenderMode.Animate - what this site uses - plays the enter animation in pure CSS straight from the served HTML.

Does it respect prefers-reduced-motion?

Yes, by the policy you choose at registration. With BmReducedMotionMode.User transforms, layout and dimension changes snap while opacity and colour still animate - softer than switching everything off. <BmotionConfig ReduceMotion="true"> forces it for a subtree.

Start animating

One package, one service - and every element on the page can move.

dotnet add package Bit.Bmotion
Bmotion 0 el · 0 active ▸
An unhandled error has occurred. Reload 🗙