---
title: useParallax
description: "Creates parallax effects easily. Uses `useDeviceOrientation` on mobile devices and falls back to mouse position on desktop. `roll$` and `tilt$` are reactive observables scaled to -0.5 ~ 0.5, and `source$` reports the active sensor source (`deviceOrientation` or `mouse`)."
category: Sensors
type-table:
  import: "@usels/web"
  name: "UseParallax"
  params:
    children:
      - UseParallaxOptions
---

## Demo

## Usage

<CodeTabs>
  <Fragment slot="hook">
    ```tsx twoslash
    // @noErrors
    import { useRef$ } from "@usels/core";
    import { useParallax } from "@usels/web";

    function ParallaxCard() {
      const el$ = useRef$<HTMLDivElement>();
      const { roll$, tilt$, source$ } = useParallax(el$);

      return (
        <div
          ref={el$}
          style={{
            transform: `rotateX(${roll$.get() * 20}deg) rotateY(${tilt$.get() * 20}deg)`,
            transition: "transform 0.1s ease-out",
          }}
        >
          <p>Source: {source$.get()}</p>
        </div>
      );
    }
    ```

  </Fragment>
  <Fragment slot="scope">
    ```tsx
    import { createRef$ } from "@usels/core";
    import { createParallax } from "@usels/web";

    function ParallaxCard() {
      "use scope";
      const el$ = createRef$<HTMLDivElement>();
      const { roll$, tilt$, source$ } = createParallax(el$);

      return (
        <div
          ref={el$}
          style={{
            transform: `rotateX(${roll$.get() * 20}deg) rotateY(${tilt$.get() * 20}deg)`,
            transition: "transform 0.1s ease-out",
          }}
        >
          <p>Source: {source$.get()}</p>
        </div>
      );
    }
    ```

  </Fragment>
</CodeTabs>

### Custom adjust functions

Scale or invert the raw sensor output via the four `*Adjust` callbacks.

<CodeTabs>
  <Fragment slot="hook">
    ```tsx
    function ParallaxCard() {
      const el$ = useRef$<HTMLDivElement>();
      const { roll$, tilt$ } = useParallax(el$, {
        mouseTiltAdjust: (v) => v * 2,
        mouseRollAdjust: (v) => v * 0.5,
      });

      return <div ref={el$}>Tilt: {tilt$.get()}</div>;
    }
    ```

  </Fragment>
  <Fragment slot="scope">
    ```tsx
    function ParallaxCard() {
      "use scope";
      const el$ = createRef$<HTMLDivElement>();
      const { roll$, tilt$ } = createParallax(el$, {
        mouseTiltAdjust: (v) => v * 2,
        mouseRollAdjust: (v) => v * 0.5,
      });

      return <div ref={el$}>Tilt: {tilt$.get()}</div>;
    }
    ```

  </Fragment>
</CodeTabs>

### Reactive options

Pass an `Observable` callback to change the adjustment function at runtime.

```typescript
import { observable } from "@usels/core";

const tiltAdjust$ = observable((v: number) => v * 2);
const { tilt$ } = useParallax(el$, { mouseTiltAdjust: tiltAdjust$ });

// Later — change the adjust function reactively
tiltAdjust$.set((v: number) => v * 3);
```

## Notes

`options` is `DeepMaybeObservable`. Each option field can be a plain value or an `Observable`. The four adjust callbacks (`deviceOrientationTiltAdjust`, `deviceOrientationRollAdjust`, `mouseTiltAdjust`, `mouseRollAdjust`) are passed as plain functions or `Observable` functions.
