What You'll Build

A dragon cursor effect is an interactive custom cursor animation built with SVG, CSS, and JavaScript where a dragon follows the mouse pointer, rotates toward it, and trails behind with segmented motion effects.

In this tutorial, you'll create an interactive dragon cursor effect entirely from scratch — no libraries, no canvas, just clean HTML, CSS, SVG, and vanilla JavaScript. The result is a fully animated dragon that tracks your mouse, rotates to face it, and trails behind with realistic body segment motion.

This is one of the most impressive creative cursor effects you can build for a portfolio, gaming site, or interactive landing page. It combines SVG animation, JavaScript mouse tracking, and CSS transforms into a single cohesive effect.


Key Features of This Dragon Cursor Effect

🐉
Animated SVG Dragon
Fully custom SVG structure with head, body segments, wings, and tail.
🖱️
Real-Time Mouse Tracking
The dragon head rotates and moves toward the cursor position in real time.
🌀
Trailing Body Animation
Each body segment follows the previous with a natural delay for a snake-like trail.
📐
Math.atan2 Direction Logic
Precise angle calculation ensures the dragon always faces the cursor perfectly.
requestAnimationFrame Loop
60fps smooth animation using the native browser animation API — no setInterval.
Accessibility Aware
Respects prefers-reduced-motion — animation pauses for users who need it.
🎨
CSS Idle Animation
Idle breathing and wing-flap animations keep the dragon alive even when still.
🚀
Zero Dependencies
Pure HTML, CSS, SVG, and JavaScript — no libraries, no build tools.

HTML — index.html
CSS — style.css

How It Works — Step by Step

Let's break down the seven core techniques that power this dragon cursor effect, from SVG structure to the animation loop.

01

SVG Dragon Structure

The dragon is built using grouped <g> elements inside an <svg> tag. Each part — head, body segment, wing, and tail — is a separate group with its own transform-origin, enabling independent rotation without affecting the rest of the body.

02

CSS Idle Animations

Even when the mouse is still, the dragon stays alive. CSS @keyframes apply a gentle scale pulse to the body (breathing) and a rotation oscillation to the wings (flapping). Each part uses a different animation-delay for a natural, offset rhythm.

03

Capturing Mouse Position

A mousemove listener on the document stores the cursor's event.clientX and event.clientY into a target object. The actual movement toward that target happens separately inside the animation loop — not directly on the event — to keep rendering smooth.

04

Math.atan2 — Angle Calculation

Math.atan2(targetY - currentY, targetX - currentX) returns the angle (in radians) from the dragon's head to the cursor. Converting to degrees and applying it as a CSS rotate() transform makes the head always face the mouse, no matter where it moves.

05

Trailing Body Segments

An array stores the last N cursor positions (one per body segment). On each animation frame, the head moves toward the mouse, then each body segment is placed at an earlier entry in the position history. This lag makes the body realistically trail behind the head like a snake in motion.

06

requestAnimationFrame Loop

The main update function calls itself recursively with requestAnimationFrame(update). This syncs the animation to the display's refresh rate (~60fps), preventing over-rendering and ensuring buttery-smooth motion without setInterval timing drift.

07

prefers-reduced-motion Support

Before starting the loop, the code checks window.matchMedia('(prefers-reduced-motion: reduce)').matches. If the user has requested reduced motion in their OS settings, the animation loop does not start. This ensures the effect is accessible and compliant with WCAG 2.1 guidelines.

⚠️ Desktop Only: Custom cursor effects only work on devices with a mouse pointer. On mobile and tablet (touch input), no cursor exists. Add a check like if ('ontouchstart' in window) return; before starting the animation to skip it on touch devices gracefully.

JavaScript & SVG Concepts Used

This project is an excellent way to practice these intermediate-to-advanced web techniques:

  • SVG Grouping & Transforms — Using <g> tags with transform-origin for modular, independently animated parts.
  • JavaScript TrigonometryMath.atan2(), Math.cos(), and Math.sin() for direction and smooth interpolation.
  • requestAnimationFrame — Building a performant 60fps animation loop that syncs with the browser's paint cycle.
  • Positional Array History — Storing past positions in an array to create trailing motion effects.
  • CSS Keyframe Animations — Layering multiple @keyframes with different delays to simulate breathing and wing motion.
  • Accessibility — Detecting and respecting prefers-reduced-motion for inclusive design.
  • Event Delegation — Capturing mouse events at the document level for global coverage.

Video Demo

Watch the dragon cursor effect in action before diving into the code:


Frequently Asked Questions

How do I create a custom cursor effect with JavaScript?
Hide the default cursor with cursor: none on the body. Create an SVG or HTML element for your custom cursor. Listen to mousemove and update the element's position using event.clientX and event.clientY. Apply CSS transforms for smooth positioning. Full source code is in the tabs above.
How does the dragon trailing body animation work?
The trail effect stores an array of past cursor positions — one entry per frame. Each body segment is rendered at an older entry in the array, offset by a fixed number of frames. This delay makes each segment appear to follow the one ahead of it, creating a fluid snake-like trailing motion.
What is Math.atan2 used for in cursor animations?
Math.atan2(y, x) returns the angle (in radians) between the positive x-axis and the point (x, y). In this project it calculates the direction from the dragon's head to the cursor, allowing the head to rotate and always face the mouse position precisely.
Will this cursor animation hurt page performance?
No — when built correctly with requestAnimationFrame, the animation runs at exactly the display refresh rate and never over-renders. Avoid updating DOM positions directly inside the mousemove handler; always defer rendering to the animation frame for best performance.
Does a custom cursor work on mobile?
No. Mobile and tablet devices use touch input — there is no mouse cursor. Add a check like if ('ontouchstart' in window) return; at the start of your script to gracefully skip the animation on touch devices and avoid any wasted computation.
How do I support prefers-reduced-motion?
Check window.matchMedia('(prefers-reduced-motion: reduce)').matches before starting the animation loop. If it returns true, skip starting requestAnimationFrame entirely and optionally show a static version of the cursor instead. This respects WCAG 2.1 accessibility guidelines.

Conclusion

The dragon cursor effect is one of the most visually striking things you can build with vanilla web technologies. By combining SVG modular structure, JavaScript trigonometry, a position history trail, and a requestAnimationFrame loop, you get a production-quality interactive animation with zero dependencies.

Whether you're building a gaming site, a creative portfolio, or just want to master advanced JavaScript animation techniques, this project covers the real-world patterns that matter. Copy the code, customize the SVG dragon design, and make it yours.

Found this useful? Check out the related projects in the sidebar for more creative web animations.