Skip to content
Sensors

useParallax

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).

Parallax
Mouse

Move your mouse over the card to see the parallax effect. On mobile, device orientation is used instead.

Hover me
Tilt (Y)
0.000
Roll (X)
0.000
Source
mouse
import {
const useRef$: {
<T = any>(initialValue: null): Ref$<T | null>;
<T = any>(initialValue: T): Ref$<T>;
<T = any>(): Ref$<T | null>;
}
useRef$
} from "@usels/core";
import {
const useParallax: (target: MaybeEventTarget, options?: DeepMaybeObservable<UseParallaxOptions>) => UseParallaxReturn
useParallax
} from "@usels/web";
function
function ParallaxCard(): JSX.Element
ParallaxCard
() {
const
const el$: Ref$<HTMLDivElement | null>
el$
=
useRef$<HTMLDivElement>(): Ref$<HTMLDivElement | null> (+2 overloads)

Core (framework-agnostic) version of useRef$. Creates an observable element ref with opaque wrapping.

  • non-null value → Ref$<T>: current, get(), peek() return T
  • null / no arg → Ref$<T | null>: current, get(), peek() return T | null

Nullability is expressed via the type parameter, mirroring T | null at the call site.

useRef$
<
interface HTMLDivElement
HTMLDivElement
>();
const {
const roll$: ReadonlyObservable<number>

Roll value. Scaled to -0.5 ~ 0.5

roll$
,
const tilt$: ReadonlyObservable<number>

Tilt value. Scaled to -0.5 ~ 0.5

tilt$
,
const source$: ReadonlyObservable<UseParallaxSource>

Sensor source: 'deviceOrientation' or 'mouse'

source$
} =
function useParallax(target: MaybeEventTarget, options?: DeepMaybeObservable<UseParallaxOptions>): UseParallaxReturn

Framework-agnostic parallax tracker. Picks the best available sensor source (deviceOrientation when the device reports live data, otherwise mouse) and exposes reactive roll$ / tilt$ observables scaled to -0.5 ~ 0.5.

Must be called inside a useScope factory — it composes createDeviceOrientation, createScreenOrientation, and createMouseInElement, all of which register scope-managed listeners.

useParallax
(
const el$: Ref$<HTMLDivElement | null>
el$
);
return (
<
JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
RefAttributes<HTMLDivElement>.ref?: Ref<HTMLDivElement> | undefined

Allows getting a ref to the component instance. Once the component unmounts, React will set ref.current to null (or call the ref with null if you passed a callback ref).

ref
={
const el$: Ref$<HTMLDivElement | null>
el$
}
HTMLAttributes<HTMLDivElement>.style?: CSSProperties | undefined
style
={{
StandardLonghandProperties<string | number, string & {}>.transform?: Property.Transform | undefined

This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2015.

Syntax: none | <transform-list>

Initial value: none

| Chrome | Firefox | Safari | Edge | IE | | :-----: | :-------: | :-------: | :----: | :-----: | | 36 | 16 | 9 | 12 | 10 | | 1 -x- | 3.5 -x- | 3.1 -x- | | 9 -x- |

transform
: `rotateX(${
const roll$: ReadonlyObservable<number>

Roll value. Scaled to -0.5 ~ 0.5

roll$
.
ImmutableObservableBase<number>.get(trackingType?: TrackingType | GetOptions): {}
get
() * 20}deg) rotateY(${
const tilt$: ReadonlyObservable<number>

Tilt value. Scaled to -0.5 ~ 0.5

tilt$
.
ImmutableObservableBase<number>.get(trackingType?: TrackingType | GetOptions): {}
get
() * 20}deg)`,
StandardShorthandProperties<string | number, string & {}>.transition?: Property.Transition<string & {}> | undefined

This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2015.

Syntax: <single-transition>#

| Chrome | Firefox | Safari | Edge | IE | | :-----: | :-----: | :-------: | :----: | :----: | | 26 | 16 | 9 | 12 | 10 | | 1 -x- | | 3.1 -x- | | |

transition
: "transform 0.1s ease-out",
}}
>
<
JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>Source: {
const source$: ReadonlyObservable<UseParallaxSource>

Sensor source: 'deviceOrientation' or 'mouse'

source$
.
ImmutableObservableBase<UseParallaxSource>.get(trackingType?: TrackingType | GetOptions): {}
get
()}</
JSX.IntrinsicElements.p: DetailedHTMLProps<HTMLAttributes<HTMLParagraphElement>, HTMLParagraphElement>
p
>
</
JSX.IntrinsicElements.div: DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
div
>
);
}

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

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>;
}

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

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);

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.

ParameterTypeDescription
targetMaybeEventTarget-
optionsUseParallaxOptions (optional)-
OptionTypeDefaultDescription
deviceOrientationTiltAdjust((value: number) => number)-Adjust device orientation tilt value
deviceOrientationRollAdjust((value: number) => number)-Adjust device orientation roll value
mouseTiltAdjust((value: number) => number)-Adjust mouse tilt value
mouseRollAdjust((value: number) => number)-Adjust mouse roll value

UseParallaxReturn

NameTypeDescription
roll$ReadonlyObservable<number>Roll value. Scaled to -0.5 ~ 0.5
tilt$ReadonlyObservable<number>Tilt value. Scaled to -0.5 ~ 0.5
source$ReadonlyObservable<UseParallaxSource>Sensor source: ‘deviceOrientation’ or ‘mouse’

View on GitHub