Skip to content
Sveltier
Mode
Primitives

Motion

Animate with the theme's timing, in CSS or in script, and hold still when the user asks for less motion.

Timing tokens

Every theme sets three durations and one easing curve: --sv-duration-fast, --sv-duration-normal, --sv-duration-slow and --sv-ease. The durations are Fibonacci milliseconds, 144, 233 and 377 in Monolith. When the user asks for reduced motion, the base styles set every duration to 0.01ms whatever the theme, so anything timed with the tokens becomes instant without checking the setting itself.

panel.css
.panel {
  transition:
    opacity var(--sv-duration-normal) var(--sv-ease),
    transform var(--sv-duration-normal) var(--sv-ease);
}

.panel[data-closed] {
  opacity: 0;
  transform: translateY(8px);
}

Animate only transform and opacity. The browser moves them without recalculating layout or repainting, so motion stays smooth on slow devices.

Transitions

For content that mounts and unmounts, fade, rise and pop are Svelte transitions that read the timing of the theme where the element is. They move only opacity and transform, and the tokens make them instant under reduced motion.

Transition
Transfer sent €1,250.00 To Alex Morgan, reference 4471

Hide and show the receipt with each transition. Switch theme packs to feel their timing, or turn on reduced motion in your system settings to see it become instant.

Receipt.svelte
<script>
  import { rise } from 'sveltier';
  let shown = $state(false);
</script>

<button aria-expanded={shown} onclick={() => (shown = !shown)}>Receipt</button>

{#if shown}
  <!-- Or in:pop out:fade, or rise with { distance: 13 }. -->
  <div transition:rise>Transfer sent: €1,250.00</div>
{/if}
NameTypeDefaultDescription
durationnumberthe theme's normal durationLength in ms. Under reduced motion the theme duration is 0.01ms.
delaynumber0Wait before starting, in ms.
distancenumber8rise only: how far the element travels, in px.
scalenumber0.944pop only: the scale it grows from, 1 − φ⁻⁶.

Springs

spring() returns a Svelte Spring with one of three presets. Stiffness steps down the φ series, 1/φ³, 1/φ⁴ and 1/φ⁵, and damping is what is left of 1. Use snappy for small controls, standard for most movement and gentle for large surfaces and numbers that count. While the user prefers reduced motion, every update lands at once.

  • snappy 38.2%
  • standard 38.2%
  • gentle 38.2%

Rebalance to move all three to the other side of the golden split. With reduced motion turned on, they jump there at once.

Balance.svelte
<script>
  import { spring } from 'sveltier';
  const balance = spring(248190.35, 'gentle');
</script>

<button onclick={() => (balance.target += 1000)}>Deposit 1,000</button>

<!-- target is where it is going; current is what to show. -->
<p class="amount">{balance.current.toFixed(2)}</p>
NameTypeDefaultDescription
spring(value, preset)<T>(value: T, preset?: SpringPreset) => Spring<T>'standard'A Svelte Spring with a preset. Set target to move it and render current. While the user prefers reduced motion, updates land at once unless set() is called with instant: false.
snappy{ stiffness: 0.236, damping: 0.764 }–1/φ³. Small, quick things: toggles, thumbs, indicators.
standard{ stiffness: 0.146, damping: 0.854 }–1/φ⁴, close to Svelte's own default. Most movement.
gentle{ stiffness: 0.09, damping: 0.91 }–1/φ⁵. Large surfaces and numbers that count up or down.

Timing in script

motion() reads the timing where an element is, for element.animate() and for Svelte's Tween. Like the CSS, it follows the theme in scope and drops to 0.01ms under reduced motion.

price-cell.ts
import { Tween } from 'svelte/motion';
import { easing, motion } from 'sveltier';

// element.animate() takes the theme's easing as it is.
export function flash(cell: HTMLElement) {
  const { fast, ease } = motion(cell);
  cell.animate([{ opacity: 0.382 }, { opacity: 1 }], { duration: fast, easing: ease });
}

// Tween needs a function: easing() turns the curve into one.
export function progress(element: HTMLElement) {
  const { slow, ease } = motion(element);
  return new Tween(0, { duration: slow, easing: easing(ease) });
}
NameTypeDescription
motion(element)(element: Element) => MotionThe timing where the element is: fast, normal and slow in ms, and ease as a CSS easing. Call it in the browser, from an attachment, an effect or a handler.
easing(ease)(ease: string) => (t: number) => numberA CSS easing as a function. Reads cubic-bezier() and the keywords; anything else falls back to ease.
cubicBezier(x1, y1, x2, y2)(x1: number, y1: number, x2: number, y2: number) => (t: number) => numberAn easing function from control points, as CSS defines them.