Parallax Floating
A component that creates a parallax floating effect on cursor/touch movement. Works also with videos, svgs, or any type of html elements.
Installation
1pnpm dlx shadcn add @fancy/parallax-floating
Usage
There are two components exported from the source file: Floating and FloatingElement. The first one is a wrapper component that takes care of the animation, mouse position tracking and other logic. The second one is a component that you must use to wrap any elements you want to float.
Floating Example
1<Floating>2 <FloatingElement depth={0.5}>3 <div className="absolute top-1/2 left-1/4 bg-red-500" />4 </FloatingElement>5 <FloatingElement depth={1}>6 <div className="absolute top-1/2 left-2/4 bg-green-500" />7 </FloatingElement>8 <FloatingElement depth={2}>9 <div className="absolute top-1/2 left-3/4 bg-blue-500" />10 </FloatingElement>11</Floating>
The advantage of this setup is that you can style and position your elements however you want using Tailwind classes or custom CSS directly on the FloatingElement component, while the Floating wrapper component handles all the complex animation logic. Simply wrap your positioned elements with FloatingElement, set their depth value, and the floating effect will be applied while maintaining your original styling and positioning.
Understanding the component
If you're curious how it works, here's a quick overview of the component's internals:
-
Element Registration: Using React Context, each
FloatingElementchild registers itself with the parentFloatingcomponent, providing its DOM reference and depth value. -
Mouse Position Tracking: The component tracks mouse movement across the screen using a custom hook that provides normalized coordinates relative to the container.
-
Animation Loop: Using Framer Motion's
useAnimationFrame, the component runs a continuous animation loop that:- Calculates the target position for each element based on the mouse coordinates
- Applies linear interpolation (lerp) to smoothly transition elements to their new positions
- Updates the transform property of each element using CSS transforms
-
Strength: The floating effect is customized through two main factors:
- Individual
depthvalues on eachFloatingElementdetermine how far that element moves. The higher the depth, the farther the element will move. - The global
sensitivityprop controls the overall intensity of the movement
- Individual
-
Lerp: The
easingFactorprop determines how quickly elements move toward their target positions - lower values create smoother, more gradual movements while higher values create snappier responses.
Notes
Z-Index Management
The Floating component focuses solely on movement animation and does not handle z-index stacking. You'll need to manually set appropriate z-index values on your FloatingElement components to achieve the desired layering effect. The depth prop only controls the intensity of the floating movement, not the visual stacking order.
Performance Optimization
For better performance when dealing with multiple floating elements, you can use a grouping strategy:
- Instead of creating individual
FloatingElementcomponents for each item, group related items under a singleFloatingElement - All children of a
FloatingElementwill move together with the same depth value - This reduces the number of elements being calculated and transformed
For example, if you have 6 floating images, instead of creating 6 separate FloatingElement components, you could group them into 3 pairs. This reduces the animation calculations from 6 to 3.
Directional Control
With the depth and sensitivity props, you can control the direction, and strength of the floating effect:
-
Positive Values: Elements move toward the mouse cursor
- Higher values create stronger movement
- Example:
depth={2}moves twice as far asdepth={1}
-
Negative Values: Elements move away from the mouse cursor
- Creates an inverse floating effect
- Example:
depth={-1}moves in the opposite direction of the mouse
Credits
Ported to Framer by Framer University
Props
| Prop | Type | Default | Description |
|---|---|---|---|
children* | React.ReactNode | - | The content to be displayed |
| sensitivity | number | 0.1 | The sensitivity of the movement |
| easingFactor | number | 0.05 | The easing factor of the movement |
| className | string | - | Additional CSS classes for styling |
FloatingElement
| Prop | Type | Default | Description |
|---|---|---|---|
children* | React.ReactNode | - | The content to be displayed |
| depth | number | 1 | The depth of the element |
| className | string | - | Additional CSS classes for styling |