Skip to main content

Parallax

Info:Media
3

A layered banner whose layers drift on scroll or follow the cursor, static with no JS or reduced motion.

layered banner scroll effect depth hero banner

Live demo

live · @xtyle/astro

Parallax

Scroll the page: the layers drift at different depths and the clouds slide sideways (`data-direction="e"`). With JavaScript off or reduced-motion on, the banner is a static layered composition.

Into the valley

A layered banner that drifts as you scroll.

Move your cursor across this one (`mode="cursor"`): the layers follow the pointer in 2D for a depth effect.

Follow the cursor

The scene shifts with your pointer.

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.

Put an Image or two behind the content with ascending data-speeds (0.3, 0.6) for a layered depth effect; leave the content layer without a data-speed so it stays put.
Drop a Stack of Heading / Text / Button as the content layer for a hero band that reads as a normal centered banner with no JS.
Pair with Section above and below for a full page-header shape.

Props

3 props, straight from the manifest.

PropTypeDefaultBindingsDescription
min-height string 22rem
html svelte astro
The band's minimum height (any CSS length).
amplitude number 80
html svelte astro
The maximum travel of a `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).
mode "scroll" | "cursor" scroll
html svelte astro
What drives the drift: `scroll` links it to the banner passing through the viewport; `cursor` makes the layers follow the pointer.

Anatomy

The named parts that make up the component, with their selectors.

banner

xtyle-parallax

The clipping band that stacks the layers and centers the content.

--bg-1 --radius-lg

content

xtyle-parallax > :not([data-speed])

A layer with no data-speed: it holds still on top, padded and centered.

--space-6

Tokens & coverage

What the component consumes, checked live against what the algorithm produces.

Success:fully covered 3/3 consumed tokens produced default register: 299 tokens

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-6

Slots

default
html svelte astro

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

The banner is a plain container; the meaning lives in the slotted content (a Heading, a Button), so structure it as you would any hero.
Give a purely-decorative background layer an empty alt, so assistive tech skips it.
Under prefers-reduced-motion the layers never move; the banner stays a static layered composition.

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>