Documentation

Documentation

Cursor

Cursor is a powerful React component for building creative and interactive cursor effects. Effortlessly replace the default browser cursor, create engaging follow-cursor animations, or add magnetic snapping to UI elements.

Built on Motion's layout animations, Cursor is performant and full customisable with variants, CSS and custom React components.

<Cursor />

Cursor is exclusive to Motion+ members. Motion+ is a one-time payment, lifetime membership that unlocks exclusive components, premium examples and access to a private Discord community.

Features

  • Two modes: Easily switch between replacing the default cursor or creating a "follow" cursor effect.

  • State-aware: Automatically adapts its appearance when hovering over links, buttons, or selectable text, and when pressed.

  • Magnetic: Make the cursor snap to interactive elements on hover for a tactile feel.

  • Customisable: Use CSS, Motion variants, and custom React components to create any cursor you can imagine.

  • Accessible: Can be disabled for users who prefer reduced motion.

Install

First, add the Motion+ library to your project using your private token. You need to be a Motion+ member to generate a private token.

npm install https://api.motion.dev/registry\?package\=motion-plus\&version\=1.5.4\&token

Once installed, Cursor can be imported via motion-plus/react:

import { Cursor } from "motion-plus/react"

Usage

The Cursor component is used for both custom cursor and follow cursor effects:

import { Cursor } from "motion-plus/react"

When Cursor is rendered, a default custom cursor will render on the page, hiding the browser's default cursor.

<Cursor />

You can remove the cursor and restore the browser cursor at any time by removing the component.

{isCursorVisible ? <Cursor /> : null}

Styling

By default, the cursor is a neutral grey color. It's possible to change the cursor's styles using CSS.

<Cursor className="my-cursor" style={{ backgroundColor: "red" }} />

Styling border-radius

Cursor uses Motion's layout animations to animate its width and height via performant transforms. As such, borderRadius currently needs to be set via the style prop, or an animation prop like animate, whileHover etc, to enable scale correction:

<Cursor style={{ borderRadius: 5 }} />

Variants

The Cursor component and its children have access to special variants that you can use to animate based on the cursor state.

const variants = {
  pressed: { scale: 0.5, filter: "blur(5px)" }
}

return <Cursor variants={variants} />

Available variants are:

  • default: Base cursor state

  • text: When hovering text

  • pointer: When hovering a link or button

  • pressed: When the mouse is pressed

  • magnetic: When the cursor is magnetically snapped to a target

  • exit: During exit animations

Custom content

When Cursor is passed children, it's width and height will stop reacting to press and text targets, and become the size of its content.

<Cursor>
  <p>Custom content!</p>
</Cursor>

If width or height are passed via style, this behaviour will be overridden.

<Cursor style={{ width: 100 }}>
  <p>Custom content!</p>
</Cursor>

Exit animations

The Cursor component already wraps children with AnimatePresence which means children have access to the exit prop. This enables exit animations as you add/remove custom content:

<Cursor>
  {showCustomContent ? (<motion.div exit={{ opacity: 0 }} />) : null}
</Cursor>

To enable exit animations on the cursor itself, you can also wrap it in AnimatePresence:

<AnimatePresence>
  {isCursorVisible ? <Cursor /> : null}
</AnimatePresence>

It has default exit animations included, but these can be customised by an exit variant:

const variants = {
  exit: { opacity: 0 }
}

return <Cursor variants={variants} />

Follow cursor

By default, Cursor will replace the browser cursor. By setting follow, it will follow it instead.

<Cursor follow />

Note: Enabling follow will change some custom cursor styles, and make the default offset to the bottom right of the browser cursor.

Magnetic snapping

By setting the magnetic prop, the Cursor will magnetically snap to the target element on hover.

<Cursor magnetic />

The intensity of the snap can be adjusted by passing a snap option as a strength value between 0 and 1.

<Cursor magnetic={{ snap: 1 }} />

By setting morph to false, the Cursor will retain its size when magnetically attracted to a target.

<Cursor magnetic={{ morph: false }} />

useMagneticPull

It's also possible to apply a magnetic pull in the opposite direction, on an element towards the cursor, using the useMagneticPull hook.


This hook can be used together, or independently of Cursor.

import { useMagneticPull } from "motion-plus/react"

It accepts a ref of a potential target element, like a button or a. When this element is hovered, the returned motion values will update with the transforms required to pull an element towards the cursor.

const ref = useRef(null)
const { x, y } = useMagneticPull(ref, 0.1)

return <motion.button ref={ref} style={{ x, y }} />

Cursor state

It's possible to read the cursor state anywhere in your app with the useCursorState hook. A Cursor component doesn't need to be rendered for this hook to work.

import { useCursorState } from "motion-plus/react"

const { type, isPressed, fontSize } = useCursorState()

Available state values are:

  • type: "pointer" | "default" | "text"

  • isPressed: boolean

  • fontSize: number, or null if no selectable text is currently hovered.

  • target: The hovered target element.

  • targetBoundingBox: A viewport-relative bounding box object of the hovered active target, or null if none.

  • zone: The value of the closest hovered data-cursor-zone attribute.

It's possible to manually change type via HTML by passing data-cursor to any element:

<section data-cursor="pointer"></section>

useCursorState also makes it possible to provide different dimensions for the default pointer.

const { type } = useCursorState()

const size = {
  width: type === "pointer" ? 50 : 20,
  height: type === "pointer" ? 50 : 20
}

return <Cursor style={size} />

Zones

It's possible to adapt our cursor (or even add/remove one) based on the currently hovered "zone", or area of the web page.

We can define a zone with the data-cursor-zone attribute:

<img data-cursor-zone="gallery-preview" />

We can then use useCursorState() to respond when the cursor enters or leaves this zone:

const { zone } = useCursorState()

return (
  <Cursor style={cursor}>
    {zone === "gallery-preview" ? (
        <p style={caption}>View gallery</p>
    ) : null}
  </Cursor>
)

We often want to change a custom cursor (or even enable/disable one) based on the currently hovered "zone" or area of the web page.

For instance, in this next example the <img /> tags have a data-cursor-zone="message" attribute. When the cursor enters these elements we can pass the name of the active zone via useCursorState():

const { zone } = useCursorState()return ( <Cursor style={cursor}> {zone === "message" ? ( <p style={caption}>View gallery</p> ) : null} </Cursor>)

Equally, we could:

  • Change the cursor color

  • Change the mix-blend-mode

  • Change size/shape

  • Add/remove a custom cursor

Accessibility

Custom cursors can be disabled for users who have enabled reduced motion in their OS settings using the useReducedMotion hook.

const shouldReduceMotion = useReducedMotion()

return shouldReduceMotion ? null : <Cursor />

Options

Cursor renders a motion.div, so it supports most of the same props. It also supports the following options:

follow

Default: false

By default, Cursor will replace the browser cursor. Set follow to replace this

<Cursor follow>
  <p>I am following the mouse</p>
</Cursor>

Note: Enabling follow will disable the custom cursor styles, so you will need to render your own content.

center

Default: In cursor mode, { x: 0.5, y: 0.5 } (center) and in follow mode { x: 0, y: 0 } (top left)

center defines an x/y point on the Cursor to use as the hit point. Or to put it another way, it defines which part of the rendered Cursor element is centered over the user's cursor.

By passing { x: 0.5, y: 0.5 } the center of the rendered Cursor element will overlay the user's cursor. Whereas, by passing { x: 0, y: 0 } the top/left of the Cursor will overlay the user's cursor, rendering the Cursor element off to the bottom/right of the cursor.

<Cursor center={{ x: 0, y: 0.5 }} />

offset

Default: false

An x/y point, defined in pixels, that can shift the cursor around the center point. Use this to get pixel-perfect accuracy with aligning custom cursor.

<Cursor offset={{ x: -1, y: -1 }} />

spring

Default: false

Defines a spring to attach to pointer movement. You can use this to trail the pointer movement with a delay.

<Cursor follow spring={{ stiffness: 500, mass: 2 }} />

matchTextSize

Default: true

The default custom cursor will match the text size of the hovered text (if selectable). Use this to disable that behaviour.

<Cursor matchTextSize={false} />

magnetic

Default: false

If true, the Cursor will magnetically snap to active targets (clickable elements).

<Cursor magnetic />

By default, it will also morph to the shape of the target, but it's possible to pass some options to adjust this behaviour.

morph

Default: true

Whether to morph the width/height of the Cursor when a target is hovered.

<Cursor magnetic={{ morph: false }} />

snap

Default: 0.8

A snap strength value between 0 and 1.

  • 0 means there's no snapping and the cursor will follow the user's cursor freely.

  • 1 is total snapping, the cursor won't react to the pointer until the target is no longer hovered.

<Cursor magnetic={{ snap: 0.2 }} />

padding

Default: 5

A value, in pixels, to add padding to the morphed cursor size.

<Cursor magnetic={{ padding: 0 }} />

Cursor is a powerful React component for building creative and interactive cursor effects. Effortlessly replace the default browser cursor, create engaging follow-cursor animations, or add magnetic snapping to UI elements.

Built on Motion's layout animations, Cursor is performant and full customisable with variants, CSS and custom React components.

<Cursor />

Cursor is exclusive to Motion+ members. Motion+ is a one-time payment, lifetime membership that unlocks exclusive components, premium examples and access to a private Discord community.

Features

  • Two modes: Easily switch between replacing the default cursor or creating a "follow" cursor effect.

  • State-aware: Automatically adapts its appearance when hovering over links, buttons, or selectable text, and when pressed.

  • Magnetic: Make the cursor snap to interactive elements on hover for a tactile feel.

  • Customisable: Use CSS, Motion variants, and custom React components to create any cursor you can imagine.

  • Accessible: Can be disabled for users who prefer reduced motion.

Install

First, add the Motion+ library to your project using your private token. You need to be a Motion+ member to generate a private token.

npm install https://api.motion.dev/registry\?package\=motion-plus\&version\=1.5.4\&token

Once installed, Cursor can be imported via motion-plus/react:

import { Cursor } from "motion-plus/react"

Usage

The Cursor component is used for both custom cursor and follow cursor effects:

import { Cursor } from "motion-plus/react"

When Cursor is rendered, a default custom cursor will render on the page, hiding the browser's default cursor.

<Cursor />

You can remove the cursor and restore the browser cursor at any time by removing the component.

{isCursorVisible ? <Cursor /> : null}

Styling

By default, the cursor is a neutral grey color. It's possible to change the cursor's styles using CSS.

<Cursor className="my-cursor" style={{ backgroundColor: "red" }} />

Styling border-radius

Cursor uses Motion's layout animations to animate its width and height via performant transforms. As such, borderRadius currently needs to be set via the style prop, or an animation prop like animate, whileHover etc, to enable scale correction:

<Cursor style={{ borderRadius: 5 }} />

Variants

The Cursor component and its children have access to special variants that you can use to animate based on the cursor state.

const variants = {
  pressed: { scale: 0.5, filter: "blur(5px)" }
}

return <Cursor variants={variants} />

Available variants are:

  • default: Base cursor state

  • text: When hovering text

  • pointer: When hovering a link or button

  • pressed: When the mouse is pressed

  • magnetic: When the cursor is magnetically snapped to a target

  • exit: During exit animations

Custom content

When Cursor is passed children, it's width and height will stop reacting to press and text targets, and become the size of its content.

<Cursor>
  <p>Custom content!</p>
</Cursor>

If width or height are passed via style, this behaviour will be overridden.

<Cursor style={{ width: 100 }}>
  <p>Custom content!</p>
</Cursor>

Exit animations

The Cursor component already wraps children with AnimatePresence which means children have access to the exit prop. This enables exit animations as you add/remove custom content:

<Cursor>
  {showCustomContent ? (<motion.div exit={{ opacity: 0 }} />) : null}
</Cursor>

To enable exit animations on the cursor itself, you can also wrap it in AnimatePresence:

<AnimatePresence>
  {isCursorVisible ? <Cursor /> : null}
</AnimatePresence>

It has default exit animations included, but these can be customised by an exit variant:

const variants = {
  exit: { opacity: 0 }
}

return <Cursor variants={variants} />

Follow cursor

By default, Cursor will replace the browser cursor. By setting follow, it will follow it instead.

<Cursor follow />

Note: Enabling follow will change some custom cursor styles, and make the default offset to the bottom right of the browser cursor.

Magnetic snapping

By setting the magnetic prop, the Cursor will magnetically snap to the target element on hover.

<Cursor magnetic />

The intensity of the snap can be adjusted by passing a snap option as a strength value between 0 and 1.

<Cursor magnetic={{ snap: 1 }} />

By setting morph to false, the Cursor will retain its size when magnetically attracted to a target.

<Cursor magnetic={{ morph: false }} />

useMagneticPull

It's also possible to apply a magnetic pull in the opposite direction, on an element towards the cursor, using the useMagneticPull hook.


This hook can be used together, or independently of Cursor.

import { useMagneticPull } from "motion-plus/react"

It accepts a ref of a potential target element, like a button or a. When this element is hovered, the returned motion values will update with the transforms required to pull an element towards the cursor.

const ref = useRef(null)
const { x, y } = useMagneticPull(ref, 0.1)

return <motion.button ref={ref} style={{ x, y }} />

Cursor state

It's possible to read the cursor state anywhere in your app with the useCursorState hook. A Cursor component doesn't need to be rendered for this hook to work.

import { useCursorState } from "motion-plus/react"

const { type, isPressed, fontSize } = useCursorState()

Available state values are:

  • type: "pointer" | "default" | "text"

  • isPressed: boolean

  • fontSize: number, or null if no selectable text is currently hovered.

  • target: The hovered target element.

  • targetBoundingBox: A viewport-relative bounding box object of the hovered active target, or null if none.

  • zone: The value of the closest hovered data-cursor-zone attribute.

It's possible to manually change type via HTML by passing data-cursor to any element:

<section data-cursor="pointer"></section>

useCursorState also makes it possible to provide different dimensions for the default pointer.

const { type } = useCursorState()

const size = {
  width: type === "pointer" ? 50 : 20,
  height: type === "pointer" ? 50 : 20
}

return <Cursor style={size} />

Zones

It's possible to adapt our cursor (or even add/remove one) based on the currently hovered "zone", or area of the web page.

We can define a zone with the data-cursor-zone attribute:

<img data-cursor-zone="gallery-preview" />

We can then use useCursorState() to respond when the cursor enters or leaves this zone:

const { zone } = useCursorState()

return (
  <Cursor style={cursor}>
    {zone === "gallery-preview" ? (
        <p style={caption}>View gallery</p>
    ) : null}
  </Cursor>
)

We often want to change a custom cursor (or even enable/disable one) based on the currently hovered "zone" or area of the web page.

For instance, in this next example the <img /> tags have a data-cursor-zone="message" attribute. When the cursor enters these elements we can pass the name of the active zone via useCursorState():

const { zone } = useCursorState()return ( <Cursor style={cursor}> {zone === "message" ? ( <p style={caption}>View gallery</p> ) : null} </Cursor>)

Equally, we could:

  • Change the cursor color

  • Change the mix-blend-mode

  • Change size/shape

  • Add/remove a custom cursor

Accessibility

Custom cursors can be disabled for users who have enabled reduced motion in their OS settings using the useReducedMotion hook.

const shouldReduceMotion = useReducedMotion()

return shouldReduceMotion ? null : <Cursor />

Options

Cursor renders a motion.div, so it supports most of the same props. It also supports the following options:

follow

Default: false

By default, Cursor will replace the browser cursor. Set follow to replace this

<Cursor follow>
  <p>I am following the mouse</p>
</Cursor>

Note: Enabling follow will disable the custom cursor styles, so you will need to render your own content.

center

Default: In cursor mode, { x: 0.5, y: 0.5 } (center) and in follow mode { x: 0, y: 0 } (top left)

center defines an x/y point on the Cursor to use as the hit point. Or to put it another way, it defines which part of the rendered Cursor element is centered over the user's cursor.

By passing { x: 0.5, y: 0.5 } the center of the rendered Cursor element will overlay the user's cursor. Whereas, by passing { x: 0, y: 0 } the top/left of the Cursor will overlay the user's cursor, rendering the Cursor element off to the bottom/right of the cursor.

<Cursor center={{ x: 0, y: 0.5 }} />

offset

Default: false

An x/y point, defined in pixels, that can shift the cursor around the center point. Use this to get pixel-perfect accuracy with aligning custom cursor.

<Cursor offset={{ x: -1, y: -1 }} />

spring

Default: false

Defines a spring to attach to pointer movement. You can use this to trail the pointer movement with a delay.

<Cursor follow spring={{ stiffness: 500, mass: 2 }} />

matchTextSize

Default: true

The default custom cursor will match the text size of the hovered text (if selectable). Use this to disable that behaviour.

<Cursor matchTextSize={false} />

magnetic

Default: false

If true, the Cursor will magnetically snap to active targets (clickable elements).

<Cursor magnetic />

By default, it will also morph to the shape of the target, but it's possible to pass some options to adjust this behaviour.

morph

Default: true

Whether to morph the width/height of the Cursor when a target is hovered.

<Cursor magnetic={{ morph: false }} />

snap

Default: 0.8

A snap strength value between 0 and 1.

  • 0 means there's no snapping and the cursor will follow the user's cursor freely.

  • 1 is total snapping, the cursor won't react to the pointer until the target is no longer hovered.

<Cursor magnetic={{ snap: 0.2 }} />

padding

Default: 5

A value, in pixels, to add padding to the morphed cursor size.

<Cursor magnetic={{ padding: 0 }} />

Cursor is a powerful React component for building creative and interactive cursor effects. Effortlessly replace the default browser cursor, create engaging follow-cursor animations, or add magnetic snapping to UI elements.

Built on Motion's layout animations, Cursor is performant and full customisable with variants, CSS and custom React components.

<Cursor />

Cursor is exclusive to Motion+ members. Motion+ is a one-time payment, lifetime membership that unlocks exclusive components, premium examples and access to a private Discord community.

Features

  • Two modes: Easily switch between replacing the default cursor or creating a "follow" cursor effect.

  • State-aware: Automatically adapts its appearance when hovering over links, buttons, or selectable text, and when pressed.

  • Magnetic: Make the cursor snap to interactive elements on hover for a tactile feel.

  • Customisable: Use CSS, Motion variants, and custom React components to create any cursor you can imagine.

  • Accessible: Can be disabled for users who prefer reduced motion.

Install

First, add the Motion+ library to your project using your private token. You need to be a Motion+ member to generate a private token.

npm install https://api.motion.dev/registry\?package\=motion-plus\&version\=1.5.4\&token

Once installed, Cursor can be imported via motion-plus/react:

import { Cursor } from "motion-plus/react"

Usage

The Cursor component is used for both custom cursor and follow cursor effects:

import { Cursor } from "motion-plus/react"

When Cursor is rendered, a default custom cursor will render on the page, hiding the browser's default cursor.

<Cursor />

You can remove the cursor and restore the browser cursor at any time by removing the component.

{isCursorVisible ? <Cursor /> : null}

Styling

By default, the cursor is a neutral grey color. It's possible to change the cursor's styles using CSS.

<Cursor className="my-cursor" style={{ backgroundColor: "red" }} />

Styling border-radius

Cursor uses Motion's layout animations to animate its width and height via performant transforms. As such, borderRadius currently needs to be set via the style prop, or an animation prop like animate, whileHover etc, to enable scale correction:

<Cursor style={{ borderRadius: 5 }} />

Variants

The Cursor component and its children have access to special variants that you can use to animate based on the cursor state.

const variants = {
  pressed: { scale: 0.5, filter: "blur(5px)" }
}

return <Cursor variants={variants} />

Available variants are:

  • default: Base cursor state

  • text: When hovering text

  • pointer: When hovering a link or button

  • pressed: When the mouse is pressed

  • magnetic: When the cursor is magnetically snapped to a target

  • exit: During exit animations

Custom content

When Cursor is passed children, it's width and height will stop reacting to press and text targets, and become the size of its content.

<Cursor>
  <p>Custom content!</p>
</Cursor>

If width or height are passed via style, this behaviour will be overridden.

<Cursor style={{ width: 100 }}>
  <p>Custom content!</p>
</Cursor>

Exit animations

The Cursor component already wraps children with AnimatePresence which means children have access to the exit prop. This enables exit animations as you add/remove custom content:

<Cursor>
  {showCustomContent ? (<motion.div exit={{ opacity: 0 }} />) : null}
</Cursor>

To enable exit animations on the cursor itself, you can also wrap it in AnimatePresence:

<AnimatePresence>
  {isCursorVisible ? <Cursor /> : null}
</AnimatePresence>

It has default exit animations included, but these can be customised by an exit variant:

const variants = {
  exit: { opacity: 0 }
}

return <Cursor variants={variants} />

Follow cursor

By default, Cursor will replace the browser cursor. By setting follow, it will follow it instead.

<Cursor follow />

Note: Enabling follow will change some custom cursor styles, and make the default offset to the bottom right of the browser cursor.

Magnetic snapping

By setting the magnetic prop, the Cursor will magnetically snap to the target element on hover.

<Cursor magnetic />

The intensity of the snap can be adjusted by passing a snap option as a strength value between 0 and 1.

<Cursor magnetic={{ snap: 1 }} />

By setting morph to false, the Cursor will retain its size when magnetically attracted to a target.

<Cursor magnetic={{ morph: false }} />

useMagneticPull

It's also possible to apply a magnetic pull in the opposite direction, on an element towards the cursor, using the useMagneticPull hook.


This hook can be used together, or independently of Cursor.

import { useMagneticPull } from "motion-plus/react"

It accepts a ref of a potential target element, like a button or a. When this element is hovered, the returned motion values will update with the transforms required to pull an element towards the cursor.

const ref = useRef(null)
const { x, y } = useMagneticPull(ref, 0.1)

return <motion.button ref={ref} style={{ x, y }} />

Cursor state

It's possible to read the cursor state anywhere in your app with the useCursorState hook. A Cursor component doesn't need to be rendered for this hook to work.

import { useCursorState } from "motion-plus/react"

const { type, isPressed, fontSize } = useCursorState()

Available state values are:

  • type: "pointer" | "default" | "text"

  • isPressed: boolean

  • fontSize: number, or null if no selectable text is currently hovered.

  • target: The hovered target element.

  • targetBoundingBox: A viewport-relative bounding box object of the hovered active target, or null if none.

  • zone: The value of the closest hovered data-cursor-zone attribute.

It's possible to manually change type via HTML by passing data-cursor to any element:

<section data-cursor="pointer"></section>

useCursorState also makes it possible to provide different dimensions for the default pointer.

const { type } = useCursorState()

const size = {
  width: type === "pointer" ? 50 : 20,
  height: type === "pointer" ? 50 : 20
}

return <Cursor style={size} />

Zones

It's possible to adapt our cursor (or even add/remove one) based on the currently hovered "zone", or area of the web page.

We can define a zone with the data-cursor-zone attribute:

<img data-cursor-zone="gallery-preview" />

We can then use useCursorState() to respond when the cursor enters or leaves this zone:

const { zone } = useCursorState()

return (
  <Cursor style={cursor}>
    {zone === "gallery-preview" ? (
        <p style={caption}>View gallery</p>
    ) : null}
  </Cursor>
)

We often want to change a custom cursor (or even enable/disable one) based on the currently hovered "zone" or area of the web page.

For instance, in this next example the <img /> tags have a data-cursor-zone="message" attribute. When the cursor enters these elements we can pass the name of the active zone via useCursorState():

const { zone } = useCursorState()return ( <Cursor style={cursor}> {zone === "message" ? ( <p style={caption}>View gallery</p> ) : null} </Cursor>)

Equally, we could:

  • Change the cursor color

  • Change the mix-blend-mode

  • Change size/shape

  • Add/remove a custom cursor

Accessibility

Custom cursors can be disabled for users who have enabled reduced motion in their OS settings using the useReducedMotion hook.

const shouldReduceMotion = useReducedMotion()

return shouldReduceMotion ? null : <Cursor />

Options

Cursor renders a motion.div, so it supports most of the same props. It also supports the following options:

follow

Default: false

By default, Cursor will replace the browser cursor. Set follow to replace this

<Cursor follow>
  <p>I am following the mouse</p>
</Cursor>

Note: Enabling follow will disable the custom cursor styles, so you will need to render your own content.

center

Default: In cursor mode, { x: 0.5, y: 0.5 } (center) and in follow mode { x: 0, y: 0 } (top left)

center defines an x/y point on the Cursor to use as the hit point. Or to put it another way, it defines which part of the rendered Cursor element is centered over the user's cursor.

By passing { x: 0.5, y: 0.5 } the center of the rendered Cursor element will overlay the user's cursor. Whereas, by passing { x: 0, y: 0 } the top/left of the Cursor will overlay the user's cursor, rendering the Cursor element off to the bottom/right of the cursor.

<Cursor center={{ x: 0, y: 0.5 }} />

offset

Default: false

An x/y point, defined in pixels, that can shift the cursor around the center point. Use this to get pixel-perfect accuracy with aligning custom cursor.

<Cursor offset={{ x: -1, y: -1 }} />

spring

Default: false

Defines a spring to attach to pointer movement. You can use this to trail the pointer movement with a delay.

<Cursor follow spring={{ stiffness: 500, mass: 2 }} />

matchTextSize

Default: true

The default custom cursor will match the text size of the hovered text (if selectable). Use this to disable that behaviour.

<Cursor matchTextSize={false} />

magnetic

Default: false

If true, the Cursor will magnetically snap to active targets (clickable elements).

<Cursor magnetic />

By default, it will also morph to the shape of the target, but it's possible to pass some options to adjust this behaviour.

morph

Default: true

Whether to morph the width/height of the Cursor when a target is hovered.

<Cursor magnetic={{ morph: false }} />

snap

Default: 0.8

A snap strength value between 0 and 1.

  • 0 means there's no snapping and the cursor will follow the user's cursor freely.

  • 1 is total snapping, the cursor won't react to the pointer until the target is no longer hovered.

<Cursor magnetic={{ snap: 0.2 }} />

padding

Default: 5

A value, in pixels, to add padding to the morphed cursor size.

<Cursor magnetic={{ padding: 0 }} />

Related topics

Motion+

Motion+

Motion+

Level up your animations with Motion+

Unlock the full vault of 290+ Motion examples, premium APIs, private Discord and GitHub, and powerful VS Code animation editing tools.

One-time payment, lifetime updates.

Motion is supported by the best in the industry.