Parallax
A layered banner whose layers drift on scroll or follow the cursor, static with no JS or reduced motion.
Live demo
Parallax stacks its children into one banner: CSS lays every child in the same grid cell, so the layers overlay and the content centers over the background with no JavaScript at all. Give a layer a data-speed and the runtime shifts it (the faster the speed, the deeper the drift), while a layer with no data-speed (the content) holds still on top.
In the default scroll mode the shift is scroll-linked as the banner passes through the viewport; set mode="cursor" and the layers follow the pointer instead. Each moving layer picks its own travel axis with data-direction (a compass token like n/se, or an angle in degrees clockwise from north), so layers can drift up, sideways, diagonally, or opposite one another; a cursor-mode layer with no direction follows the pointer in full 2D. The whole effect is an enhancement: with JavaScript off the layers sit at rest, and under prefers-reduced-motion the runtime leaves them alone, so the banner is always a legible layered composition and never depends on the motion to make sense. min-height sizes the band and amplitude scales how far the layers travel.
When to use
How this component composes with the rest of the set.
Props
4 props, straight from the manifest.
| Prop | Type | Default | Bindings | Description |
|---|---|---|---|---|
data-speed="1" layer, in pixels; each layer scales it by its own speed. A negative value flips the whole banner's direction at once (and composes with a layer's own data-speed sign). | ||||
scroll links it to the banner passing through the viewport; cursor makes the layers follow the pointer. | ||||
prefers-reduced-motion. The Svelte and raw-element paths always upgrade, so they carry no equivalent. |
Anatomy
The named parts that make up the component, with their selectors. This one renders light DOM, so the selector is the handle.
banner
The clipping band that stacks the layers and centers the content.
content
A layer with no data-speed: it holds still on top, padded and centered.
Tokens & coverage
What the component consumes, checked live against what the algorithm produces.
Live coverage check against the xtyle-default register
(derive(xtyleDefault, { anchors }) →
coverComponent(manifest, register)). Every token this component
consumes must be a key the algorithm produces.
--bg-1--radius-lg--space-6Slots
The layers, back to front. A layer with a data-speed (a number) drifts and fills the band, optionally along a data-direction axis; a negative data-speed reverses just that layer. A layer with no data-speed is the still content, centered on top.
Accessibility
Code
Layered banner
Two drifting background layers (the hills drift sideways) behind a still content layer.
<xtyle-parallax min-height="24rem" amplitude="140">
<img data-speed="0.45" src="/sky.jpg" alt="" />
<img data-speed="0.85" data-direction="w" src="/hills.png" alt="" />
<div>
<h1>Into the valley</h1>
<p>A layered banner that drifts as you scroll.</p>
</div>
</xtyle-parallax><script lang="ts">
import { Parallax, Heading, Text } from "@xtyle/svelte";
</script>
<Parallax minHeight="24rem" amplitude={140}>
<img data-speed="0.45" src="/sky.jpg" alt="" />
<img data-speed="0.85" data-direction="w" src="/hills.png" alt="" />
<div>
<Heading level={1}>Into the valley</Heading>
<Text>A layered banner that drifts as you scroll.</Text>
</div>
</Parallax>---
import Parallax from "@xtyle/astro/Parallax.astro";
import Heading from "@xtyle/astro/Heading.astro";
import Text from "@xtyle/astro/Text.astro";
---
<Parallax minHeight="24rem" amplitude={140}>
<img data-speed="0.45" src="/sky.jpg" alt="" />
<img data-speed="0.85" data-direction="w" src="/hills.png" alt="" />
<div>
<Heading level={1}>Into the valley</Heading>
<Text>A layered banner that drifts as you scroll.</Text>
</div>
</Parallax>Cursor follow
The same stack in mode="cursor": the layers track the pointer in 2D for a depth effect.
<xtyle-parallax min-height="24rem" mode="cursor" amplitude="50">
<img data-speed="0.4" src="/sky.jpg" alt="" />
<img data-speed="0.9" src="/hills.png" alt="" />
<div>
<h1>Move your cursor</h1>
<p>The layers follow the pointer for depth.</p>
</div>
</xtyle-parallax>