Lesson 1 pasted plain HTML and CSS into a page. Most projects are built with a framework, and some motions need a few lines of script. This lesson covers every format in the Code tab and how each kind of motion behaves in your code.
The formats
Open a motion and the Code tab. Along the top:
| Tab | What you get | Where it goes |
|---|---|---|
| HTML | The markup | Where the motion should appear |
| CSS | The styles and keyframes | Your stylesheet |
| JS | A few lines of script, only for click and pointer motions | Your script, after the HTML |
| React | A component with its styles inside | A .jsx or .tsx file |
| Vue | A single-file component; Vue scopes the styles to it | A .vue file |
| Svelte | A Svelte 5 component; Svelte scopes the styles to it | A .svelte file |
Each tab has a Copy button and a short hint. Copy all takes the HTML, the CSS and any script in one block, and Page .html downloads a page that plays the motion on its own.
Loops, entrances and hover: pure CSS
Most motions need no script at all:
- Loops play as soon as the HTML is on the page.
- Plays once motions play when the element appears. To replay one, remove the element and add it again, or toggle its class.
- On hover motions use
:hoverin the CSS, so they answer the pointer by themselves. On touch screens, hover happens on tap.
Click motions: three lines of script
A toggle switch, a menu button or a like button changes state on a click. The CSS styles the "on" state with an is-on class, and the JS tab writes the script that switches it. For the toggle switch:
document.querySelectorAll('.toggle-switch').forEach(el => {
el.addEventListener('click', () => {
const on = el.classList.toggle('is-on');
el.setAttribute('aria-checked', on);
});
});It also keeps aria-checked in step, so screen readers announce the switch correctly. The React, Vue and Svelte versions do the same with the framework's own state, so you do not need the JS tab there.
Pointer motions: a little more script
A 3D tilt card, a magnetic button or watching eyes follow the pointer. Their script listens to the pointer and sets a few CSS custom properties, and the CSS does the moving. The script checks for reduced motion first and does nothing when the visitor asks for less motion. In React it runs in an effect, in Vue it starts when the component mounts and stops when it unmounts, and in Svelte it is an action.
React, Vue and Svelte
The framework versions carry everything in one file:
- React: the CSS sits in the component and is added once. Rename the component as you like.
- Vue: a
<template>, a<script setup>when needed, and a<style scoped>block. - Svelte: Svelte 5 syntax, with the styles scoped by Svelte.
Text, colours and sizes are written in, as you set them in Customise. To change them from outside, turn those values into your framework's props.
Reduced motion, always
The CSS of every motion ends with a rule for people whose system asks for less motion (shortened here):
@media (prefers-reduced-motion: reduce) {
.toggle-switch, .toggle-switch * { animation: none !important; transition: none !important; }
}Every motion is designed so that its resting state means something: the spinner is drawn, the text is shown, the progress bar is full. So switching motion off never leaves an empty or broken element. Keep this rule when you copy the CSS; it costs nothing and it is what accessibility guidelines ask for.
Names that do not clash
Every class, keyframe and custom property starts with the motion's own name, such as .toggle-switch and @keyframes toggle-switch-…. You can use several motions on one page, next to your own CSS, without renaming anything.
Next: motion as a file, for places that cannot run code.