Sure! Here’s a rewritten version of the article that maintains the original meaning and structure but uses different phrasing and tone for a fresh take:
—

On desktop interfaces, the cursor is a familiar and expected part of the user experience. Yet, most websites avoid altering it — and for good reason. Changing the cursor can disrupt user expectations and potentially cause confusion. Plus, custom cursors aren’t useful on touch devices, which make up a significant portion of web traffic today.
Geoff already explored the basics of cursor styling with CSS in “Changing the Cursor with CSS for Better User Experience (or Fun)”. So here, we’ll dive into more advanced and creative ways to style cursors.
Enhancing Cursors with JavaScript
While CSS offers some neat cursor customization options, JavaScript opens the door to more dynamic and interactive designs. With JavaScript, we can turn any HTML element into a cursor, allowing us to animate it, add text, apply filters, and more — just like any other DOM element.
The basic approach involves creating a
that follows the mouse pointer using the mousemove
event. We can even add effects like a scale animation on click by listening for the mousedown
event.
Now we’ve got ourselves a custom cursor that responds to clicks and follows the user’s movement. But the default system cursor is still visible, which can be distracting. To fix that, we can hide it using cursor: none
in CSS — though note that some browsers might still show the cursor if the page doesn’t fill the full height.
To ensure our custom cursor doesn’t interfere with interactions, we’ll add pointer-events: none
to it. We can also enhance interactivity by changing the cursor’s appearance when hovering over interactive elements, using a class like pressable
.
With that, we’ve got a sleek circular cursor that feels much more personalized and responsive.
Accessibility, Fallbacks, and Touch Devices
Touchscreen users don’t use cursors, so there’s no need to show our custom one in that context. Additionally, for users who prefer reduced motion (a setting for accessibility), it’s a good idea to disable animated cursors altogether.
We can detect these settings with JavaScript and only activate our custom cursor when appropriate:
const isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0;
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
if (!isTouchDevice && !prefersReducedMotion && cursor) {
// Initialize custom cursor here
}
This approach ensures that our custom cursor only appears when JavaScript is running and the user’s device and preferences allow for it. Otherwise, the browser’s default cursor behavior will take over.
To keep things consistent, we can also define a fallback cursor in CSS that mimics the look of our custom one. For example, here’s how to use a base64-encoded SVG circle as a fallback:
html {
cursor: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMiIgaGVpZ2h0PSIzMiIgdmlld0JveD0iMCAwIDMyIDMyIj4KICA8Y2lyY2xlIGN4PSIxNiIgY3k9IjE2IiByPSIxNiIgZmlsbD0iYmxhY2siIC8+Cjwvc3ZnPg==") 16 16, auto;
}
This sets a 32×32 pixel black circle as the cursor, with the hotspot centered at (16, 16).
Pushing the Limits
This is just the tip of the iceberg. Once you have a custom cursor in place