CSS Driver

Lightweight CSS transition-based animations

The @tamagui/animations-css package provides lightweight, typed animations through CSS transitions on web.

Installation

yarn add @tamagui/animations-css

Configuration

Add it to your Tamagui config:

import { createAnimations } from '@tamagui/animations-css'
import { createTamagui } from 'tamagui'
export default createTamagui({
animations: createAnimations({
fast: { duration: 150, bounce: 0.2 },
medium: { duration: 300, bounce: 0.15 },
slow: 'ease-in 450ms',
}),
// ...
})

The config format is the same for all four drivers, so a name means the same motion whichever driver renders it. See Animations for the shipped table.

The root entry contains CSS component transitions only. If your app uses useAnimatedNumber, useAnimatedNumberStyle, useAnimatedNumbersStyle, or useAnimatedNumberReaction, import the same factory from the extras entry:

import { createAnimations } from '@tamagui/animations-css/extras'

Sheet uses animated numbers for its position and Toast uses them for swipe gestures, so apps using either component with the CSS driver need the extras entry. The root entry keeps apps that only use CSS transitions from shipping the JavaScript spring and linked-style runtime.

How it works

At runtime, the plugin does very little except to set the transition property in CSS. At compile-time, the compiler does the same, ensuring you get all the benefits of prop removal and view flattening even when using animations.

Animation configuration

A config entry is a spring, written as { duration, bounce }:

createAnimations({
quick: { duration: 220, bounce: 0.3 },
bouncy: { duration: 400, bounce: 0.5 },
})

Springs work under this driver: they compile to a linear() easing that traces the real spring curve, overshoot included, with no JavaScript running.

An entry can also be a plain CSS timing string, in <easing-function> <duration> order or the CSS order:

createAnimations({
quick: 'ease-out 100ms',
slow: 'ease-in-out 500ms',
})

Delay

<Square transition={{ preset: 'quick', delay: 200 }} />

The delay (in milliseconds) is applied as CSS transition-delay. A CSS transition string spells it the CSS way, transition="200ms ease-out 100ms".

Supported easing functions

  • ease: default easing (equivalent to cubic-bezier(0.25, 0.1, 0.25, 1))
  • linear: no easing, constant speed
  • ease-in: slow start
  • ease-out: slow end
  • ease-in-out: slow start and end
  • cubic-bezier(x1, y1, x2, y2): custom cubic bezier curve

When to use

Advantages:

  • Smallest bundle size: minimal JavaScript overhead
  • Broad compatibility: works everywhere CSS works
  • Compiler optimizations: benefits from static extraction

Limitations:

  • Springs are sampled into a linear() easing up front, so they can’t react to an interruption mid-flight the way a running JS spring can
  • Limited to CSS animatable properties
  • Less control over animation lifecycle

Example

import { createAnimations } from '@tamagui/animations-css'
import { YStack, createTamagui } from 'tamagui'
const animations = createAnimations({
quick: { duration: 220, bounce: 0.3 },
bouncy: { duration: 400, bounce: 0.5 },
})
export default createTamagui({
animations,
// ... rest of config
})
// Usage in components
export const MyComponent = () => (
<YStack transition="quick" scale="hover:1.1" />
)

See also