⮌ back | Overview | Home

🚟The Move Animation

The motion animation moves the content of a transition group along two connected edges in 3D space. For live examples visit the animation demo page and select one of the move presets in the button grid at the top of the page.

Contents

Why would I use this component?

Astro allows users to create their own animations for view transitions. The astro-vtbot move animation is a ready-made solution that can be easily inserted into Astro’s transition:animate property. It also supports parameters for fine-tuning the animation to your needs. It is even possible to customize the underlying keyframes when used together with the <AnimationStyle/> component.

Usage

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

Basic usage

The most basic usage is to apply the move() animation without any parameters. This will use the default values for the animation.

MyComponent.astro
1
---
2
import { move } from "astro-vtbot/animations/move";
3
---
4
...
5
<h1 transition:animate={move()}>Move</h1>
6
...

The effect will in a first step move the old-image away from the viewer into the background and than with the second step move it to the left. The new-image uses the first step to move in from the right. That happens in the background. In the second step the image is moved to the front.

❗ Perspective

Please note that 3D-effects require the CSS perspective property to be set on a parent of the transformed element.

For browsers that natively support view transition good choices for that parent are the ::view-transition-group or ::view-transition-image-pair pseudo element, which is the parent of the ::view-transition-old and ::view-transition-new pseudo elements.

animation.css
1
::view-transition-image-pair(*) {
2
perspective: 50cm;
3
}

The animations offered by the Bag of Tricks generate this for you, so you are already save on browsers that natively support view transitions.

For browsers that do not natively support view transitions, there are no such pseudo elements. For Astro’s fallback mode for view transitions to work properly with 3D animations, you have to set the perspective on a regular HTML element that is a parent of the animated element in the DOM.

Here is how this is done in the animation demo:

AnimationMdxLayout.astro
1
...
2
<div style="perspective: 50cm">
3
<div id="demo">
4
<a href="./#">Flip</a>
5
<slot />
6
<br style="clear:both" />
7
</div>
8
</div>
9
...

Clipping

The same applies to clipping: To support browsers that do not implement native view transitions, set overflow to clip on a parent element in the DOM. For browsers that support native view transitions, set it to the ::view-transition-group or ::view-transition-image-pair pseudo-elements. Unlike perspective, overflow is not set by default as it is not clear whether you want clip or visible. In future versions you may be able to set this with a parameter.

AnimationMdxLayout.astro
1
...
2
<div style="perspective: 50cm; overflow: clip">
3
<div id="demo">
4
...
5
</div>
6
</div>
7
<style>
8
::view-transition-image-pair(*) {
9
overflow: clip;
10
}
11
<style>

Parametrized usage

The default values for the animation can be overwritten by passing an object with the desired values to the move() function. The following example shows how to change the duration and easing of the animation.

MyComponent.astro
1
---
2
import { move } from "astro-vtbot/animations/move";
3
---
4
...
5
<h1 transition:animate={move({duration:'1.5s', easing: 'cubic-bezier(.16,.73,.05,1.52)' })}>Move</h1>
6
...

You can set the following parameters:

Property nameCSS propertyDefault value
durationanimation-duration0.15s
easinganimation-timing-functionease-in-out
delayanimation-delay(see below)
directionanimation-directionnormal
fillModeanimation-fill-modeboth

If you explicitly set a value for the delay, this value is used for both the in and out animation. This is typically not what you want. If you want to use different values for the in and out animation, use the customMove function as described in the next section.

Extended parametrized usage

If you want to use more than the 5 properties supported by move() or want to have more control over the animations keyframes, you can use the customMove() function. This function takes a name for the transition and an object with the following optional properties:

The function returns a scope identifier to be used with the data-astro-transition-scope attribute of the HTML element you want to animate. Under the hood, customMove() generates a style sheet with keyframe information and the defined CSS properties. You need to add these extended styles to your page by using the <AnimationStyle/> component. Note: Only use <AnimationStyle/> in conjunction with customMove(), not with move().

MyComponent.astro
1
---
2
import { customMove } from "astro-vtbot/animations/move";
3
import AnimationStyle from "astro-vtbot/animations/AnimationStyle.astro";
4
5
const moveScope = customMove('myMove', {
6
keyframes: {
7
enter: { y: '-50cm', z: '-50cm' },
8
enterMid: { y: '10cm', z: '-25cm', angel: '10deg' },
9
leaveMid: { y: '-10cm', z: '-25cm', angel: '-10deg' },
10
leave: { y: '50cm', z: '50cm' },
11
axis: { x: 1, y: 1, z: 1 }
12
}
13
base: { duration: '300ms' },
14
extensions: {
15
forwards: { new: { 'animation-delay': '0.2s' } },
16
backwards: { new: { 'animation-delay': '0.2s' } },
17
},
18
});
19
---
20
...
21
<AnimationStyle name="myMove"/>
22
<h1 data-astro-transition-scope={moveScope}>Move</h1>
23
...

Keyframes

The keyframes object of the customMove() function has the following properties:

1
type MoveKeyframeParameter = {
2
enter?: { x?: string; y?: string; z?: string, angel?: string; };
3
enterMid?: { x?: string; y?: string; z?: string, angel?: string; };
4
leaveMid?: { x?: string; y?: string; z?: string, angel?: string; };
5
leave?: { x?: string; y?: string; z?: string, angel?: string; };
6
axis?: { x?: number; y?: number; z?: number; };
7
};

The two edges for moving the new image onto the page are enter to enterMid and enterMid to final. The two edges for moving the old image out are original to leaveMid and leaveMid to leave. Here original and final are the natural positions of the image. There coordinates are implicit. For the other endpoints enter, enterMid, leaveMid and leave give relative positions on all three axis. In addition to these moves, the image can also be rotated at the endpoints (with values of 0deg for original and final). For the other endpoints the rotation is around the same axis which is defined by axis. The default values for all keyframe parameters are all 0 with the exception of axis.z = 1.

The values are used as parameters of the keyframe definition in

this style sheet template
Move.css.template
1
@keyframes ${keyframeNamePrefix}FwdMoveOut {
2
from {
3
transform: translate3d(0, 0, 0) rotate3d(1, 0, 0, 0);
4
opacity: 1;
5
}
6
50% {
7
transform: translate3d(${leaveXm}, ${leaveYm}, ${leaveZm}) rotate3d(${x}, ${y}, ${z}, ${leaveAm});
8
opacity: 1;
9
}
10
to {
11
transform: translate3d(${leaveX}, ${leaveY}, ${leaveZ}) rotate3d(${x}, ${y}, ${z}, ${leaveA});
12
opacity: 0;
13
}
14
}
15
@keyframes ${keyframeNamePrefix}FwdMoveIn {
16
from {
17
transform: translate3d(${enterX}, ${enterY}, ${enterZ}) rotate3d(${x}, ${y}, ${z}, ${enterA});
18
opacity: 0;
19
}
20
50% {
21
transform: translate3d(${enterXm}, ${enterYm}, ${enterZm}) rotate3d(${x}, ${y}, ${z}, ${enterAm});
22
opacity: 1;
23
}
24
to {
25
transform: translate3d(0, 0, 0) rotate3d(1,0,0,0);
26
opacity: 1;
27
}
28
}
29
@keyframes ${keyframeNamePrefix}BwdMoveOut {
30
from {
31
transform: translate3d(0, 0, 0) rotate3d(1,0,0,0);
32
opacity: 1;
33
}
34
50% {
35
transform: translate3d(${enterXm}, ${enterYm}, ${enterZm}) rotate3d(${x}, ${y}, ${z}, ${enterAm});
36
opacity: 1;
37
}
38
to {
39
transform: translate3d(${enterX}, ${enterY}, ${enterZ}) rotate3d(${x}, ${y}, ${z}, ${enterA});
40
opacity: 0;
41
}
42
}
43
@keyframes ${keyframeNamePrefix}BwdMoveIn {
44
from {
45
transform: translate3d(${leaveX}, ${leaveY}, ${leaveZ}) rotate3d(${x}, ${y}, ${z}, ${leaveA});
46
opacity: 0;
47
}
48
50% {
49
transform: translate3d(${leaveXm}, ${leaveYm}, ${leaveZm}) rotate3d(${x}, ${y}, ${z}, ${leaveAm});
50
opacity: 1;
51
}
52
to {
53
transform: translate3d(0, 0, 0) rotate3d(1, 0, 0, 0);
54
opacity: 1;
55
}
56
}
57
::view-transition-image-pair(*) {
58
perspective: 50cm;
59
}

Base

The value of the base property is used to call the move() function as defined above.

Extensions

With the extensions property you can define all those CSS properties that can not be defined by move() directly. You can specify different values for forwards and backwards, in and out animations. These values are merged with the result of callingmove() with base parameters and overwrite its properties.