⮌ back | Overview | Home

Animation Style

<AnimationStyle/> gives the user more direct control over the style sheets for Astro’s view transitions. It is accompanied by a set of functions in animation-style.ts that generate the CSS for native view transitions as well as Astro’s simulation of view transitions.

Note: While you will probably use the <AnimationStyle/> component in your own project. But most functions from animation-style.ts are rather building blocks for other components that provide view transition animations and are typically not used by end users. See Zoom and Swing for animations aimed at end users. A notable exception is the adapter() function, see description below.

Contents

Why would I use this component?

For the basic animation use case, Move, Swing and Zoom animations can simply be plugged into Astro’s transition:animate={} property. But for the more elaborated use cases with extended parametrization, the style sheets for animations during view transitions must be placed manually. The <AnimationStyle/> component gives you full control over where to place style sheets for view transitions on your pages. It generates CSS for native view transition as well as Astro’s simulation of view transitions. The contents of the style sheets are specified using functions from animation-style.ts.

Usage

Install astro-vtbot in your project running npx astro add astro-vtbot or npm install astro-vtbot.

Using <AnimationStyle>

Using this component is a two step process:

MyComponent.astro
1
---
2
import { setStyles } from 'astro-vtbot/animations/animation-style';
3
import AnimationStyle from 'astro-vtbot/animations/AnimationStyle.astro';
4
5
setStyles("superFade", styles);
6
---
7
<AnimationStyle name="superFade">

The <AnimationStyle/> component should be placed in the <head> of your page.

The call to setStyle and the <AnimationStyle/> component are linked by the common identifier superFade. The name of the animation is arbitrary, but must be the same in both places. The second parameter to setStyles() is a string with the CSS for the animation.

Creating CSS and transition scope

How do I get that CSS string for setStyles()?

You can use the styleSheet function from animation-style.ts to generate both, a CSS string for view transition animations and a transition scope id that you can use to reference the style sheet from an HTML element for which you want to define a transition group.

MyComponent.astro
1
---
2
import { ViewTransitions } from 'astro:transitions';
3
import { setStyles, styleSheet } from 'astro-vtbot/animations/animation-style';
4
import AnimationStyle from 'astro-vtbot/animations/AnimationStyle.astro';
5
6
const myFade = ...
7
const { scope, styles } = styleSheet({ transitionName: "superFade", animations: myFade });
8
setStyles("superFade", styles);
9
---
10
<html>
11
<head>
12
<ViewTransitions />
13
<AnimationStyle name="superFade">
14
...
15
</head>
16
<body>
17
...
18
<div data-astro-transition-scope={scope}>
19
...
20
</div>
21
</body>
22
</html>

The scope is an identifier that is used to bind the style sheet to the <div>. This is the same thing that happens behind the scenes when you use transition:animate in Astro. It typically has the form astro-xxxxxxxx where xxxxxxxx is a random string.

The second parameter to styleSheet() is an object that describes the CSS that should be used for the view transition. Here is an example for a fade animation:

1
const anim = {
2
old: {
3
'animation-name': 'fadeIn',
4
'animation-duration': '0.2s',
5
'animation-timing-function': 'linear',
6
'animation-fill-mode': 'forwards',
7
},
8
new: {
9
'animation-name': 'fadeOut',
10
'animation-duration': '0.3s',
11
'animation-timing-function': 'linear',
12
'animation-fill-mode': 'backwards',
13
}
14
};
15
16
const myFade = {
17
forwards: anim,
18
backwards: anim,
19
};

You might recognize this example from the Astro Docs about View Transitions. The main difference between the input of styleSheet() and the Astro custom animation example is that vtbot uses kebab-case CSS property keys, while Astro uses a small set of convenient names. See below for details.

Here myFade defines forwards and backwards animations. “Forwards” is what will normally happen when you click a link. “Backwards” is what is used when you hit the browser back button. Each branch defines the out animation for leaving the old page and the in animation for entering the new page. The animation for each branch is defined by an object with CSS properties.

Astro’s properties for custom animations are very convenient to use, while the kebab-case properties require more typing. However, supporting the full set of CSS properties is more powerful: for example, you can use transform-origin with styleSheet(). Astro’s custom animations do not support this.

NamedAnimationPairs vs. TransitionDirectionalAnimations

Here are the details about the differences between Astro’s TransitionDirectionalAnimations and the NamedAnimationPairs used by astro-bot’s styleSheet():

ObjectAstro animationvtbot animation
Object for CSS generationTransitionDirectionalAnimations: an object with forwards and backwards propertiesNamedAnimationPairs: an object that can have arbitrarily named properties including forwards and backwards
Animation pairsTransitionAnimation: old and new can be objects or arrays of objectsold and new can only be objects but not arrays
Animation propertiesTransitionAnimation: an object with entries for 6 CSS animation properties. Keys are name, delay, duration, easing, direction & fillmodeAnimationCSS: an object with any CSS properties. The keys are kebab-case CSS property names.

Reusing Astro custom animations with extended()

The animation-style.ts file also provides an extended() function that can be used to convert Astro’s TransitionDirectionalAnimations to NamedAnimationPairs. This allows you to reuse Astro’s custom animations with styleSheet().

Note: An important limitation is that Astro’s TransitionDirectionalAnimations can contain arrays, while NamedAnimationPairs can not. This means that you can only use Astro custom animations with extend() if they do not contain arrays.

MyComponent.astro
1
---
2
import { setStyles, styleSheet, extend } from 'astro-vtbot/animations/animation-style';
3
import AnimationStyle from 'astro-vtbot/animations/AnimationStyle.astro';
4
import { fade } from 'astro:transitions';
5
6
const { scope, styles } = styleSheet({
7
transitionName: 'fade',
8
animations: extend(fade({ duration: 300 })),
9
});
10
setStyles('fade', styles);
11
---
12
<AnimationStyle name="fade">
13
<div data-astro-transition-scope={scope}>
14
...
15
</div>

Using custom direction names with transition:animate={}

One use case supported by animation-style.ts is independent of the <AnimationStyle/> component. It is about supporting custom animations with transition:animate={}. Astro recognizes two direction names for view transitions: forwards and backwards. If you want to use other or additional names, you will get typing errors. It is possible to cast objects of type Record<string, TransitionAnimationPair> to Astro’s TransitionDirectionalAnimations. The more elegant and type safe way is to use the adapter() function from animation-style.ts.

Use your custom animation object or function with transition:animate by sending it through the adapter.

MyComponent.astro
1
---
2
import { adapter } from 'astro-vtbot/animations/animation-style';
3
const mySpecialAnimation = {...}
4
---
5
...
6
<div transition:animate={adapter(mySpecialAnimation)}>
7
...

Of course this also works with functions

MyComponent.astro
1
...
2
<div transition:animate={adapter(mySpecialAnimationFunction(withParameters))}>
3
...

Now you can use other direction names than forwards and backwards in your animation. Make sure to select proper direction values by setting e.direction to one of your custom direction names in the event handler for astro:before-preparation.

Incompatibility Notice For the forwards and backwards styles, you must use the divergent direction names forward and back when setting e.direction.

See this in action in the FishPond Tech Demo