Skip to main content
Version: 5.3.2

withTiming

The withTiming modifier creates precise, time-based animations with exact durations. Unlike withSpring which uses physics, withTiming gives you complete control over how long an animation takes and how it accelerates/decelerates.

Why Use withTiming?

Timing animations are perfect when you need:

  • Exact duration - Know exactly how long an animation takes
  • Predictable timing - Coordinate multiple animations
  • Smooth easing - Control acceleration and deceleration
  • Precise control - Perfect for UI transitions, tooltips, dropdowns

Basic Syntax

withTiming(toValue, options?)

Parameters

  • toValue (required): The target value. Can be a number, string, object, or array.
  • options (optional): Configuration object for timing control.

Simple Example

The simplest timing animation:

import { useValue, withTiming, animate } from 'react-ui-animate';

function MyComponent() {
const [opacity, setOpacity] = useValue(0);

return (
<>
<button onClick={() => setOpacity(withTiming(1, { duration: 300 }))}>
Fade In
</button>
<animate.div
style={{
opacity,
width: 100,
height: 100,
background: '#60a5fa',
}}
/>
</>
);
}

Configuration Options

OptionTypeDefaultDescription
durationnumber300Animation duration in milliseconds
easingfunctionLinearEasing function for acceleration/deceleration
onStart() => void-Called when animation starts
onChange(value) => void-Called on every frame with current value
onComplete() => void-Called when animation finishes

Real-World Examples

Example 1: Fade In/Out

Perfect for tooltips, dropdowns, and modals:

function FadeComponent() {
const [opacity, setOpacity] = useValue(0);

const show = () => {
setOpacity(withTiming(1, { duration: 300 }));
};

const hide = () => {
setOpacity(withTiming(0, { duration: 200 }));
};

return (
<>
<button onClick={show}>Show</button>
<button onClick={hide}>Hide</button>
<animate.div
style={{
opacity,
width: 100,
height: 100,
background: '#60a5fa',
}}
/>
</>
);
}

Example 2: Slide Animation

Smooth slide transitions:

function SlidePanel() {
const [translateX, setTranslateX] = useValue(-200);

const open = () => {
setTranslateX(withTiming(0, { duration: 400 }));
};

const close = () => {
setTranslateX(withTiming(-200, { duration: 300 }));
};

return (
<>
<button onClick={open}>Open</button>
<button onClick={close}>Close</button>
<animate.div
style={{
translateX,
width: 200,
height: '100vh',
background: 'white',
boxShadow: '2px 0 8px rgba(0,0,0,0.1)',
}}
>
Panel Content
</animate.div>
</>
);
}

Example 3: Progress Bar

Animate progress with exact timing:

function ProgressBar() {
const [width, setWidth] = useValue(0);

const start = () => {
setWidth(withTiming(100, { duration: 2000 }));
};

return (
<>
<button onClick={start}>Start Progress</button>
<div style={{ width: 300, height: 8, background: '#e1e1e1', borderRadius: 4 }}>
<animate.div
style={{
width: `${width}%`,
height: '100%',
background: '#60a5fa',
borderRadius: 4,
}}
/>
</div>
</>
);
}
Preview

Easing Functions

Control how the animation accelerates and decelerates:

// Linear - constant speed
setX(withTiming(100, { duration: 300 }));

// Ease in - slow start, fast end
setX(withTiming(100, {
duration: 300,
easing: (t) => t * t
}));

// Ease out - fast start, slow end
setX(withTiming(100, {
duration: 300,
easing: (t) => t * (2 - t)
}));

// Ease in-out - slow start and end
setX(withTiming(100, {
duration: 300,
easing: (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t
}));

Animating Multiple Values

Timing works great with objects and arrays:

const [style, setStyle] = useValue({ 
opacity: 0,
translateY: 50,
scale: 0.9
});

// Animate all properties together
setStyle(withTiming({
opacity: 1,
translateY: 0,
scale: 1
}, { duration: 400 }));

Using Callbacks

Track animation progress and trigger side effects:

function AnimatedCard() {
const [opacity, setOpacity] = useValue(0);

const fadeIn = () => {
setOpacity(withTiming(1, {
duration: 500,
onStart: () => {
console.log('Fade in started');
// Show loading indicator, disable buttons, etc.
},
onChange: (value) => {
// Track progress
console.log(`Opacity: ${(value * 100).toFixed(0)}%`);
},
onComplete: () => {
console.log('Fade in complete');
// Hide loading indicator, enable buttons, etc.
},
}));
};

return (
<>
<button onClick={fadeIn}>Fade In</button>
<animate.div
style={{
opacity,
width: 100,
height: 100,
background: '#60a5fa',
}}
/>
</>
);
}

Common Patterns

Pattern 1: Quick Fade

const [opacity, setOpacity] = useValue(0);

const show = () => {
setOpacity(withTiming(1, { duration: 200 }));
};

const hide = () => {
setOpacity(withTiming(0, { duration: 150 }));
};

Pattern 2: Coordinated Animations

const [opacity, setOpacity] = useValue(0);
const [translateY, setTranslateY] = useValue(50);

// Animate both with same duration for coordination
const reveal = () => {
setOpacity(withTiming(1, { duration: 400 }));
setTranslateY(withTiming(0, { duration: 400 }));
};

Pattern 3: Staggered Timing

const [items, setItems] = useValue([0, 0, 0, 0]);

const reveal = () => {
// Each item fades in 100ms after the previous
items.forEach((_, i) => {
setTimeout(() => {
const newItems = [...items];
newItems[i] = 1;
setItems(newItems);
}, i * 100);
});
};

When to Use withTiming vs withSpring

Use CaseRecommended ModifierWhy
TooltipswithTimingQuick, predictable timing
DropdownswithTimingSnappy, controlled
Progress barswithTimingExact duration needed
ModalswithSpringNatural, bouncy feel
ButtonswithSpringResponsive, alive
CardswithSpringOrganic motion

Best Practices

✅ Do

  • Use withTiming when you need exact duration
  • Use consistent durations across related animations
  • Use easing functions for natural acceleration/deceleration
  • Leverage callbacks for coordination and side effects

❌ Don't

  • Don't use withTiming when you want natural, bouncy motion (use withSpring)
  • Don't make animations too slow (>1000ms) - users expect quick feedback
  • Don't forget to handle the animation lifecycle with callbacks
  • Don't animate layout properties - use transforms instead

Performance Tips

  1. Timing is optimized - Very performant for simple animations
  2. Use transforms - translateX, translateY, scale are GPU-accelerated
  3. Batch updates - Animate multiple properties in one object
  4. Keep durations reasonable - 200-500ms is usually ideal

Troubleshooting

Animation feels too fast:

  • Increase duration (try 400-600ms)

Animation feels too slow:

  • Decrease duration (try 150-250ms)

Animation feels mechanical:

  • Add easing function for natural acceleration/deceleration
  • Or consider using withSpring for more natural motion

Next Steps