We lately launched CSS view-transitions in Chrome. Yay! Quickly after, individuals began innovating with it, creating cool and easy experiences.
Because it so occurs after we launch an internet function, patterns emerge of easy methods to use it, and other people are inclined to run into comparable challenges. This put up will present you examples of easy methods to deal with these challenges with a library referred to as Velvette.
CSS view-transitions in a nutshell
CSS view-transitions permit animating between two unrelated states of a doc, by giving names to components within the previous and new state, capturing these components’ snapshots into photographs, and animating these photographs in pseudo-elements. See this text for a great starter equipment.
The lacking items
The next is a abstract of (just a few) points that folks discovered troublesome to do with view transitions:
- CSS view-transitions work by having a singular identify for every taking part component, shared between the previous state and new state. In lots of instances, producing these names is tedious as each taking part component has to have a distinct one.
- View-transitions are scoped for the entire doc, so defining a
view-transition-name
for a component would seize that component each time there’s a transition ― this creates redundant captures in pages that include multiple view-transition. - Selecting easy methods to model the transition primarily based on a navigaiton requires various broilerplate JS code.
- All these issues come collectively after we attempt to create an animation between an inventory and particulars web page, which is a standard use case for view-transitions: setting the
view-transition-name
solely on the related components on the right time takes cautious precision and may in any other case be bug inclined.
Velvette
Velvette is a library that works on CSS view-transitions and supplies utilities that assist with these challenges. It’s constructed as an add-on, you’ll be able to slab it on an present website and configure it to make that web page animate between states. Progressive enhancement!
Let’s add animations to just a little films app
The flicks app (or extra like little a part of an app) is at https://github.com/noamr/velvette-codrops. It makes use of a snippet of static knowledge from TMDB, and allows you to do two issues:
- Kind an inventory of films by identify/ID/launch date
- Click on a film to see its particulars, click on it once more (or press “again”) to return to the checklist.
Obtain the repo and run a small internet server. See how switching between checklist and film, and altering the type order, each happen immediately with out an animation.
On this demo we’ll present easy methods to:
- Animate the checklist sorting, the place each component animates into place.
- Animate the navigation between the film checklist and particulars, such because the hero picture broaden/shrinks.
Putting in Velvette
Putting in velvette
works in the usual manner, by including it with npm
or through the use of a script tag.
Word: do that solely in Chrome for now…
Add this to index.html
:
<script src="https://www.unpkg.com/velvette@0.1.10-pre/dist/browser/velvette.js"></script>
This can put a Velvette
class in your window
object, and we will get going to make use of it for easy view-transitions.
Kind animation
Let’s begin with the type animation.
In index.js
, we’ve got a line chargeable for sorting when one of many radio buttons is clicked:
doc.types.sorter.addEventListener("change", () => render());
Let’s begin by having a easy transition:
doc.types.sorter.addEventListener("change", () => {
if ("startViewTransition" in doc)
doc.startViewTransition(() => render());
else
render();
});
This creates the default fade animation – the entire web page fades. It’s a begin, however not what we’re after.
Change this line with a line that animates the type, with a singular view-transition-name
for every of the weather:
doc.types.sorter.addEventListener("change", () => {
Velvette.startViewTransition({
replace: () => render(),
captures: {
"part#checklist li[:id]": "$(id)"
}
});
});
This nonetheless calls the render()
operate on each type change, but in addition invokes velvette
to start out a view-transition, the place each merchandise that matches the selector part#checklist li[id]
would have the li
‘s ID assigned to its view-transition-name
. The [:id
] half captures the ID attribute because it goes by means of the selector change, after which applies it to the identify in the long run.
Now refresh the web page and attempt to change the type. Voila, a form animation! (Could possibly be nicer, be happy to do the design work…)
Increasing/shrinking the picture
Now let’s get to the opposite half, increasing/shrinking the hero picture when going between the checklist and particulars view. Word that the present code that switches between them in index.js
makes use of the navigation API:
window.navigation.addEventListener("navigate", e => {
e.intercept({
handler() {
render();
}
});
});
To make that navigation set off a view transition, we create a velvette
configuration that defines how completely different routes in our app behave by way of CSS view-transitions:
const velvette = new Velvette({
routes: {
particulars: "?film=:movie_id",
checklist: "?checklist"
},
guidelines: [{
with: ["list", "details"], class: "broaden"
}, ],
captures: {
":root.vt-expand.vt-route-details img#hero": "movie-artwork",
":root.vt-expand.vt-route-list li#movie-$(movie_id) img": "movie-artwork"
}
});
Let’s go over what’s on this configuration:
Routes
We outline two routes, particulars
and checklist
. These routes are URL patterns. Word that the particulars
route captures a movie_id
parameter.
Guidelines
Guidelines outline which navigations ought to set off a view-transition, and which class so as to add for this view-transition. On this case, we declare that any navigation between checklist
and particulars
(in both route) ought to set off a view-transition, and add the broaden
class (which might be prefixed as vt-expand
.
Captures
Like within the type instance, we add captures: a map between a selector and a generate view-transition-name
. On this case, we wish a single view-transition-name
referred to as movie-artwork
to be utilized each to the hero picture and to the proper thumbnail (and solely the proper one), however not on the similar time – in any other case the transition can be skipped.
The primary selector takes care of the hero picture:
:root.vt-expand.vt-route-details img#hero
This may apply solely after we’re capturing the broaden
transition, and solely after we’re within the particulars
route.
The second selector takes care of the thumbnail:
:root.vt-expand.vt-route-list li#movie-$(movie_id) img
It could solely apply when within the checklist
route of the broaden
transition, and would change the $(movie_id)
string with the parameter with the identical identify from both route – on this case the particulars
route.
Intercepting the navigation
window.navigation.addEventListener("navigate", e => {
velvette.intercept(e, {
handler() {
render();
}
});
});
We let velvette
intercept the NavigateEvent
, and apply the configuration we gave it.
And right here we go, an broaden animation:
Abstract
CSS View-transition current a brand new world of alternatives with easy and spectacular UX. However there’s no want for it to be troublesome to writer. With velvette
, managing the distinctive view-transition-names
and passing parameters between navigations and components hopefully makes the developer expertise smoother, not simply the consumer expertise.
To see all the things collectively, checkout the with-velvette department.
You’ll be able to view the ultimate demo right here:
Try the reside model.