> For the complete documentation index, see [llms.txt](https://analog.groupthought.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://analog.groupthought.com/reference/alpine/parallax.md).

# x-parallax

Directives for compositor-driven scroll parallax: a root timeline and elements that translate against it.

Directives for scroll parallax: a root defines the scroll range and its elements translate against it.

| Directive / magic                   | What it does                                                                                           |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `x-parallax`                        | The root whose viewport traversal defines the parallax timeline                                        |
| `x-parallax:element`                | Translates with the root's progress. Does nothing without a parent root                                |
| `x-parallax:element.distance.200px` | Travel distance (default 10px). Accepts `px`, `%`, and `vh`; `%` is relative to the element's own size |
| `x-parallax:element.reverse`        | Moves the element against the scroll direction                                                         |
| `x-parallax:element.horizontal`     | Translates on the x axis instead of the y axis                                                         |
| `$parallax`                         | The root's state, readable anywhere inside it: `scrollValue`, a lazily tracked Motion value            |

The plugin does nothing when the visitor prefers reduced motion or the device reports low power. Elements stay where the CSS put them. Give parallax elements `will-change-transform` so the browser composites the movement.

When native scroll timelines are available, ordinary page-scrolled roots use a `ViewTimeline`, so scrolling updates their `translate3d` animation without per-frame JavaScript. Sticky roots and roots inside overflow containers use a page `ScrollTimeline` instead, preserving the same page-scroll range without letting the view timeline stall. Older browsers share one lazy JavaScript listener per active root. A root with no parallax element or `$parallax` consumer is never measured and does not install scroll tracking.

The root carries `data-parallax-active` while it intersects the viewport. Each element attaches its effect once, when the root first enters, and keeps the same anchor across leave and re-entry. The JavaScript fallback stops tracking while the root is off screen and seeds the current progress synchronously when it returns.

## Examples

### A basic parallax element

Use `x-parallax` on a clipping container and `x-parallax:element` with a `distance` on the moving part:

```html
<div class="relative h-[200px] overflow-hidden" x-parallax>
  <div
    class="absolute h-[180%] w-full will-change-transform"
    x-parallax:element.distance.200px
  >
    …
  </div>
</div>
```

Every Analog section is already a parallax root. `core-section-wrapper.liquid` puts `x-parallax` on the wrapper, so blocks and backgrounds only add `x-parallax:element`. Pair columns are their own roots instead, because stacked columns on mobile would share the section's scroll range incorrectly.

### Reverse

Use the `reverse` modifier to move the element against the scroll direction:

```html
<div x-parallax:element.reverse.distance.25%>…</div>
```

Section backgrounds work this way (`core-background.liquid`): the image is taller than its frame and drifts opposite the page, which is what the "Parallax amount" setting produces.

### Percentage and viewport distances

Use `%` or `vh` when the travel should scale with the element or the screen:

```html
<div x-parallax:element.distance.50%>…</div>
<div x-parallax:element.distance.10vh>…</div>
```

Banner layers pass the merchant's "Parallax amount" (-100 to 100) straight in as a percentage, so opposing values on two layers pull them apart as the page scrolls.

### Horizontal movement

Use the `horizontal` modifier to translate on the x axis:

```html
<div x-parallax:element.horizontal.distance.100px>…</div>
```

Collage image layers expose this as their "Direction" setting.

## Options

There is no options object. The element modifiers above are the whole API. For the merchant-facing settings built on this plugin (background parallax, per-layer parallax on Banner layers), see [Layered backgrounds](/building-pages/backgrounds.md).
