elements
lifecycle
browser
- useAudio
- useBattery
- useBluetooth
- useBreakpoints
- useBroadcastChannel
- useBrowserLocation
- useClipboard
- useCopy
- useCssVar
- useDisplayMedia
- useDocumentEvent
- useDocumentTitle
- useDocumentVisibility
- useEventListener
- useEventSource
- useEyeDropper
- useFavicon
- useFileSystemAccess
- useFps
- useFullscreen
- useGamepad
- useGeolocation
- useMeasure
- useMediaControls
- useMediaQuery
- useMemory
- useNetwork
- useObjectUrl
- useOnline
- useOtpCredential
- usePermission
- usePictureInPicture
- usePointerLock
- usePostMessage
- useRaf
- useShare
- useSpeechRecognition
- useSpeechSynthesis
- useSticky
utilities
state
user
sensors
Move your mouse over the scene — or tilt your device — to shift the layers and create depth.




Credit of images to Jarom Vogel
import { useParallax } from '@siberiacancode/reactuse';
const LAYERS = [
{
id: 'parallax-layer-0',
src: 'https://jaromvogel.com/images/design/tiger_hunt_parallax/Tiger_hunt_3.png',
multiplier: 1
},
{
id: 'parallax-layer-1',
src: 'https://jaromvogel.com/images/design/tiger_hunt_parallax/Tiger_hunt_2.png',
multiplier: 2
},
{
id: 'parallax-layer-2',
src: 'https://jaromvogel.com/images/design/tiger_hunt_parallax/Tiger_hunt_1.png',
multiplier: 3
},
{
id: 'parallax-layer-3',
src: 'https://jaromvogel.com/images/design/tiger_hunt_parallax/Tiger_hunt_0.png',
multiplier: 4
}
];
const Demo = () => {
const parallax = useParallax<HTMLDivElement>((value) => {
const card = document.getElementById('parallax-card');
if (card) {
card.style.transform = `rotateX(${value.roll * 20}deg) rotateY(${value.tilt * 20}deg)`;
}
LAYERS.forEach((layer) => {
const element = document.getElementById(layer.id);
if (!element) return;
element.style.transform = `translateX(${value.tilt * layer.multiplier * 10}px) translateY(${value.roll * layer.multiplier * 10}px)`;
});
});
return (
<section
ref={parallax.ref}
className='flex min-h-96 flex-col items-center justify-center gap-6 p-6'
>
<p className='text-muted-foreground max-w-xs text-center text-sm'>
Move your mouse over the scene — or tilt your device — to shift the layers and create depth.
</p>
<div className='perspective-[300px]'>
<div
className='border-border flex h-72 w-56 items-center justify-center overflow-hidden rounded-xl border bg-white shadow-lg transition-transform duration-300 ease-out'
id='parallax-card'
>
<div className='relative size-[4em] overflow-hidden text-6xl'>
{LAYERS.map((layer) => (
<img
key={layer.id}
alt={layer.id}
className='absolute h-full w-full transition-transform duration-300 ease-out'
id={layer.id}
src={layer.src}
/>
))}
</div>
</div>
</div>
<p className='text-muted-foreground text-xs'>
Credit of images to{' '}
<a
className='text-primary hover:underline'
href='https://codepen.io/jaromvogel'
rel='noreferrer'
target='_blank'
>
Jarom Vogel
</a>
</p>
</section>
);
};
export default Demo;
Installation
pnpm add @siberiacancode/reactuseUsage
const { snapshot, watch } = useParallax(ref, (value) => console.log(value));
// or
const { snapshot, watch } = useParallax(ref, options);
// or
const { ref, snapshot, watch } = useParallax<HTMLDivElement>((value) => console.log(value));
// or
const { ref, snapshot, watch } = useParallax<HTMLDivElement>(options);Type Declarations
import type { HookTarget } from '@/utils/helpers';
import type { StateRef } from '../useRefState/useRefState';
interface InternalDeviceOrientationValue {
absolute: boolean;
alpha: number | null;
beta: number | null;
gamma: number | null;
}
interface InternalScreenOrientationValue {
angle: number;
orientationType?: OrientationType;
}
export interface UseParallaxValue {
/** Roll value. Scaled to `-0.5 ~ 0.5` */
roll: number;
/** Sensor source, can be `mouse` or `deviceOrientation` */
source: 'deviceOrientation' | 'mouse';
/** Tilt value. Scaled to `-0.5 ~ 0.5` */
tilt: number;
}
export type UseParallaxCallback = (value: UseParallaxValue, event: Event) => void;
export interface UseParallaxOptions {
/** Callback invoked on parallax updates */
onChange?: UseParallaxCallback;
/** Device orientation roll adjust function */
deviceOrientationRollAdjust?: (value: number) => number;
/** Device orientation tilt adjust function */
deviceOrientationTiltAdjust?: (value: number) => number;
/** Mouse roll adjust function */
mouseRollAdjust?: (value: number) => number;
/** Mouse tilt adjust function */
mouseTiltAdjust?: (value: number) => number;
}
interface UseParallaxReturn {
snapshot: UseParallaxValue;
supported: boolean;
watch: () => UseParallaxValue;
}
export interface UseParallax {
(target: HookTarget, callback?: UseParallaxCallback): UseParallaxReturn;
(target: HookTarget, options?: UseParallaxOptions): UseParallaxReturn;
<Target extends Element>(
callback?: UseParallaxCallback,
target?: never
): UseParallaxReturn & {
ref: StateRef<Target>;
};
<Target extends Element>(
options?: UseParallaxOptions,
target?: never
): UseParallaxReturn & {
ref: StateRef<Target>;
};
}API
Parameters
| Name | Type | Default | Note |
|---|---|---|---|
| target | HookTarget | - | The target element for the parallax effect |
| callback | (value: UseParallaxValue, event: Event) => void | - | The callback invoked on parallax updates |
Returns
UseParallaxReturnParameters
| Name | Type | Default | Note |
|---|---|---|---|
| target | HookTarget | - | The target element for the parallax effect |
| options | UseParallaxOptions | - | The options for the parallax effect |
Returns
UseParallaxReturnParameters
| Name | Type | Default | Note |
|---|---|---|---|
| callback | (value: UseParallaxValue, event: Event) => void | - | The callback invoked on parallax updates |
Returns
UseParallaxReturn & { ref: StateRef<Target> }Parameters
| Name | Type | Default | Note |
|---|---|---|---|
| options | UseParallaxOptions | - | The options for the parallax effect |
Returns
UseParallaxReturn & { ref: StateRef<Target> }Contributors
ddebabin
Last updated on