motion
Expert guidelines for building performant animations with Motion (formerly Motion One) vanilla JavaScript animation library
What this skill does
# Motion Animation Guidelines
You are an expert in Motion (motion.dev), JavaScript, TypeScript, and web animation performance. Follow these guidelines when creating animations.
## Core Principles
### About Motion
- Motion is the JavaScript animation library from the creator of Framer Motion
- Use `motion` for vanilla JavaScript/TypeScript projects
- Use `motion/react` for React projects (see framer-motion skill)
- Designed for high performance with minimal bundle size
### Installation
```bash
npm install motion
```
### Basic Import
```javascript
import { animate, scroll, inView, timeline } from "motion";
```
## Basic Animations
### Simple Animation
```javascript
import { animate } from "motion";
// Animate a single element
animate(".element", { x: 100, opacity: 1 }, { duration: 0.5 });
// Animate with options
animate(
".element",
{ transform: "translateX(100px)" },
{
duration: 0.8,
easing: "ease-out"
}
);
```
### Keyframes
```javascript
animate(
".element",
{
x: [0, 100, 50], // Keyframe values
opacity: [0, 1, 0.5]
},
{ duration: 1 }
);
```
## Performance Optimization
### Animate Transform Properties
```javascript
// Best performance - GPU accelerated
animate(".element", {
x: 100, // translateX
y: 50, // translateY
scale: 1.2, // scale
rotate: 45, // rotate
opacity: 0.5 // opacity
});
// Avoid when possible - triggers layout
animate(".element", {
width: 200, // Causes layout recalculation
height: 150, // Causes layout recalculation
top: 50, // Causes layout recalculation
left: 100 // Causes layout recalculation
});
```
### Use will-change
```javascript
// Add will-change for transform animations
const element = document.querySelector(".element");
element.style.willChange = "transform";
animate(element, { x: 100 }, {
onComplete: () => {
element.style.willChange = "auto"; // Remove after animation
}
});
```
### Hardware Acceleration
Motion automatically uses hardware-accelerated properties when possible. For best performance:
1. Prefer `x`, `y` over `left`, `top`
2. Prefer `scale` over `width`, `height`
3. Use `opacity` for fade effects
4. Use `rotate` over `transform: rotate()`
## Timeline Animations
### Create Timelines
```javascript
import { timeline } from "motion";
const sequence = [
[".header", { y: ["-100%", 0], opacity: [0, 1] }],
[".content", { y: [50, 0], opacity: [0, 1] }, { at: "-0.3" }],
[".footer", { y: [50, 0], opacity: [0, 1] }, { at: "-0.3" }]
];
const controls = timeline(sequence, {
duration: 0.8,
defaultOptions: { easing: "ease-out" }
});
```
### Timeline Controls
```javascript
const controls = timeline(sequence);
controls.play();
controls.pause();
controls.reverse();
controls.stop();
controls.finish();
// Seek to specific time
controls.currentTime = 0.5;
```
## Scroll Animations
### Basic Scroll Animation
```javascript
import { scroll, animate } from "motion";
scroll(
animate(".progress-bar", { scaleX: [0, 1] }),
{ target: document.querySelector("article") }
);
```
### Scroll-Linked Animation
```javascript
scroll(({ y }) => {
// y.progress is 0 to 1
animate(".element", {
opacity: y.progress,
y: y.progress * 100
}, { duration: 0 });
});
```
### Scroll with Container
```javascript
scroll(
animate(".parallax", { y: [0, -100] }),
{
target: document.querySelector(".section"),
offset: ["start end", "end start"]
}
);
```
## In-View Animations
### Trigger on Visibility
```javascript
import { inView, animate } from "motion";
inView(".card", (info) => {
animate(info.target, { opacity: 1, y: 0 }, { duration: 0.5 });
// Return cleanup function
return () => {
animate(info.target, { opacity: 0, y: 20 }, { duration: 0.2 });
};
});
```
### With Options
```javascript
inView(
".element",
(info) => {
animate(info.target, { scale: [0.8, 1], opacity: [0, 1] });
},
{
margin: "-100px", // Trigger 100px before entering viewport
amount: 0.5 // Trigger when 50% visible
}
);
```
## Stagger Animations
### Stagger Multiple Elements
```javascript
import { stagger, animate } from "motion";
animate(
".list-item",
{ opacity: [0, 1], y: [20, 0] },
{ delay: stagger(0.1) }
);
```
### Stagger from Center
```javascript
animate(
".grid-item",
{ scale: [0, 1] },
{ delay: stagger(0.05, { from: "center" }) }
);
```
### Stagger with Easing
```javascript
animate(
".item",
{ x: ["-100%", 0] },
{
delay: stagger(0.1, {
easing: "ease-out",
start: 0.2
})
}
);
```
## Spring Animations
### Use Springs for Natural Motion
```javascript
animate(
".element",
{ scale: 1.2 },
{
easing: "spring",
// or with custom spring settings
easing: [0.34, 1.56, 0.64, 1] // Custom bezier curve
}
);
```
### Spring Options
```javascript
animate(".element", { x: 100 }, {
type: "spring",
stiffness: 300,
damping: 30
});
```
## Easing Functions
### Built-in Easings
```javascript
// Common easing values
animate(".element", { x: 100 }, { easing: "ease" });
animate(".element", { x: 100 }, { easing: "ease-in" });
animate(".element", { x: 100 }, { easing: "ease-out" });
animate(".element", { x: 100 }, { easing: "ease-in-out" });
animate(".element", { x: 100 }, { easing: "linear" });
// Cubic bezier
animate(".element", { x: 100 }, {
easing: [0.25, 0.1, 0.25, 1]
});
```
## Animation Controls
### Control Playback
```javascript
const controls = animate(".element", { x: 100 }, { duration: 1 });
// Control methods
controls.play();
controls.pause();
controls.stop();
controls.finish();
controls.reverse();
// Get/set time
controls.currentTime = 0.5;
console.log(controls.duration);
// Cancel animation
controls.cancel();
```
### Animation Events
```javascript
const controls = animate(
".element",
{ x: 100 },
{
duration: 1,
onComplete: () => console.log("Done!")
}
);
// Promise-based
controls.finished.then(() => {
console.log("Animation finished");
});
```
## Accessibility
### Respect Reduced Motion
```javascript
const prefersReducedMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)"
).matches;
animate(
".element",
{ x: 100, opacity: 1 },
{
duration: prefersReducedMotion ? 0 : 0.5,
easing: prefersReducedMotion ? "linear" : "ease-out"
}
);
```
### Create Accessible Wrapper
```javascript
function safeAnimate(element, keyframes, options = {}) {
const reducedMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)"
).matches;
return animate(element, keyframes, {
...options,
duration: reducedMotion ? 0 : (options.duration ?? 0.3)
});
}
```
## Integration with Frameworks
### Vanilla JavaScript
```javascript
document.addEventListener("DOMContentLoaded", () => {
animate(".hero", { opacity: [0, 1], y: [30, 0] });
});
```
### With Event Listeners
```javascript
const button = document.querySelector(".button");
button.addEventListener("mouseenter", () => {
animate(button, { scale: 1.05 }, { duration: 0.2 });
});
button.addEventListener("mouseleave", () => {
animate(button, { scale: 1 }, { duration: 0.2 });
});
```
## Cleanup
### Cancel Animations
```javascript
const controls = animate(".element", { x: 100 });
// Later, cancel it
controls.cancel();
```
### Cleanup Pattern
```javascript
class AnimatedComponent {
constructor(element) {
this.element = element;
this.animations = [];
}
animate(keyframes, options) {
const controls = animate(this.element, keyframes, options);
this.animations.push(controls);
return controls;
}
destroy() {
this.animations.forEach(anim => anim.cancel());
this.animations = [];
}
}
```
## Best Practices Summary
1. Use transform properties (x, y, scale, rotate) for best performance
2. Add will-change before complex animations, remove after
3. Use timeline for sequenced animations
4. Use scroll() for scroll-linked effects
5. Use inView() for viewport-triRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.