Samson Omojola I'm an experienced software engineer. I love creating applications with responsive, beautiful, intuitive, state-of-the-art designs. I'm skilled in HTML, CSS, JavaScript, Ionic, React, PHP, Laravel, and Flutter.

Creating a custom mouse cursor with CSS

8 min read 2264

Creating A Custom Mouse Cursor With Css

As the middleman between your users and your website, cursors can either limit or greatly enhance the way your users experience your site. This is why sleek, intentionally-designed custom cursors have become a significant part of UI and UX today.

Custom cursors are an opportunity to give your users direction in an engaging way and create a memorable, immersive experience for them on your website.

There is a wide spectrum of potential users for whom to create custom cursors. Examples include students learning from a projector, users with impaired mobility, and younger audiences being targeted by a brand.

In this tutorial, we’ll take a look at what custom cursors are and learn how to use CSS (and JavaScript) to create custom cursors that’ll give your website a creative edge. We will cover:

To follow along with this tutorial, you should have some knowledge of HTML, CSS, and JavaScript.

Overview of cursors in CSS

We already interact with custom cursors every day. When you hover over buttons and the pointer cursor changes to a hand, or you hover over text and the cursor changes to a text cursor, this interactivity is achieved through custom cursors.

However, there are many other creative experiences we can provide to our users through cursors.

Before we dive into creating our own custom cursors, you should know that CSS provides you with cursors out of the box for some frequently performed tasks.

These cursors show you what can be done at the exact location you are hovering over. Examples include cursors indicating you should click links, drag and drop elements, zoom in and out on things, and more.

All you have to do is specify the type of cursor you want using the CSS cursor property.

Some of the available cursors in CSS include:

.auto            { cursor: auto; }
.default         { cursor: default; }
.none            { cursor: none; }
.context-menu    { cursor: context-menu; }
.help            { cursor: help; }
.pointer         { cursor: pointer; }
.progress        { cursor: progress; }
.wait            { cursor: wait; }
.cell            { cursor: cell; }
.crosshair       { cursor: crosshair; }
.text            { cursor: text; }
.vertical-text   { cursor: vertical-text; }
.alias           { cursor: alias; }
.copy            { cursor: copy; }
.move            { cursor: move; }
.no-drop         { cursor: no-drop; }
.not-allowed     { cursor: not-allowed; }
.all-scroll      { cursor: all-scroll; }
.col-resize      { cursor: col-resize; }
.row-resize      { cursor: row-resize; }
.n-resize        { cursor: n-resize; }
.e-resize        { cursor: e-resize; }
.s-resize        { cursor: s-resize; }
.w-resize        { cursor: w-resize; }
.ns-resize       { cursor: ns-resize; }
.ew-resize       { cursor: ew-resize; }
.ne-resize       { cursor: ne-resize; }
.nw-resize       { cursor: nw-resize; }
.se-resize       { cursor: se-resize; }
.sw-resize       { cursor: sw-resize; }
.nesw-resize     { cursor: nesw-resize; }
.nwse-resize     { cursor: nwse-resize; }

Hover over the boxes below to see the cursors in action:

See the Pen CSS Cursors by Samson Omojola (@Caesar222)
on CodePen.

See the code and interact with the different cursors directly on CodePen.

Check out the complete list of CSS cursors here.

While these cursors are useful and have some basic styling, we can certainly get more creative with cursors.

How to create a custom cursor with CSS

Creating a custom cursor with CSS is a pretty straightforward process. The first step you have to take is to find the image you want to use to replace the default cursor. You can either design one yourself or get a free PNG that suits your needs from an icon library such as FontAwesome.

Next, point the CSS cursor property to the location of the image using url. Now the cursor property knows that it’s meant to use whatever image is at that URL as its cursor:

body {
      cursor: url(‘path-to-image.png’), auto;

To ensure that this cursor is used on all parts of your website, the best place to use the cursor property is in the body tag of your HTML. However, if you want, you can assign custom cursors to specific elements instead of the whole website.

You can also add a fallback value to your cursor property. When using custom CSS properties, this value ensures that if the image that serves as your custom property for some reason is missing or cannot be loaded, then your users will have another option.

In this case, auto is the fallback descriptor for your custom cursor property. Your users will see the regular cursor if the custom one is unavailable.

You can provide more than one custom cursor (multiple fallbacks) for your website to use. All you have to do is add their paths to the cursor property:

body {
      cursor: url(‘path-to-image.png’), url(‘path-to-image-2.svg’), url(‘path-to-image-3.jpeg’), auto;

There are three fallback cursors in the code above.

How to change a mouse cursor to a pointer

Say you have a table and you’d like for the mouse cursor to change to a pointer (i.e, the hand icon) whenever a user hovers over a row in the table. You can achieve this using the CSS cursor property.

Here’s an example:

  /* Style the table */
  table {
    font-family: arial, sans-serif;
    border-collapse: collapse;
    width: 100%;

  /* Style the table cells */
  td, th {
    border: 1px solid #dddddd;
    text-align: left;
    padding: 8px;

  /* Style the table rows */
  tr:hover {
    cursor: pointer;

    <td>New York</td>
    <td>Los Angeles</td>

In the above code, we use the tr:hover selector to apply the cursor property to all table rows when the mouse hovers over them. The cursor property is set to pointer, which changes the mouse cursor to a hand icon.

How to hide a mouse cursor with CSS

To hide the mouse cursor with CSS, you can use the cursor property and set its value to none. Here’s an example:

  /* Style the body element */
  body {
    cursor: none;

  <!-- Your content goes here -->

This will hide the mouse cursor throughout the entire webpage. If you only want to hide the mouse cursor for a specific element, you can apply the cursor property to that individual element instead of the body element.

There are several situations in which hiding the mouse cursor might be useful. For example:

  • In a game or interactive application, hiding the mouse cursor could help create a more immersive experience for the user
  • In a presentation or slideshow, hiding the mouse cursor could reduce distractions and keep the focus on the content
  • In fullscreen video or media, hiding the mouse cursor could help prevent the user from accidentally clicking on controls or other elements

Keep in mind that, depending on the use case, hiding the mouse cursor could be confusing or disorienting for some users. This strategy should be used carefully and only when necessary.

How to create a custom cursor with JavaScript

Creating a custom cursor with JavaScript involves manipulating DOM elements.

Basically, we’ll create some DOM elements which will serve as our custom cursor, and then use JavaScript to manipulate them. Then, as we move our cursor around, those custom elements will move around as our cursor.

Rather than design an image or download an image online, we are going to use CSS to design a custom cursor. I want us to use something animated that draws users in. Move your cursor around the box below to see an example of what I’m describing:

See the Pen Animated Custom CSS Cursor by Samson Omojola (@Caesar222)
on CodePen.

See the full code and interact with this cursor directly on CodePen.

As you can see, the cursor consists of two elements — one large circle and one small one. We’ll create two div elements and give them class names:

<div class="cursor small"></div>
<div class="cursor big"><div>

Next, we’ll create the circles with CSS. In the code below, we assign a width and height of 50px each to the big circle. To make it a circle, we give it a border radius of 50%.

The small circle will be hollow, so we give it a border and border radius of 50%. Then, we assign it a width and height of 6px each.

We disable the default cursor by giving cursor a value of none so that we can render the custom cursor in its place.

To add animation to the big circle, we use @keyframes.

Our animation-duration is 2.0s. At the start of this duration, we set background-color to green and opacity to 0.2. Halfway through, we set the circle’s background-color to orange. At the end of the 2 second duration, we set the circle’s background-color to red.

To make the animation repeat over and over again, we set animation-iteration-count to infinite:

  background-color: #171717;
  cursor: none;
  height: 120vh;
  width: 6px;
  height: 6px;
  border: 2px solid #fff;
  border-radius: 50%;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  margin-bottom: 20rem;
  animation-name: stretch;
            animation-duration: 2.0s;
            animation-timing-function: ease-out;
            animation-direction: alternate;
            animation-iteration-count: infinite;
            animation-play-state: running;

@keyframes stretch {
            0% {

                opacity: 0.2;
                background-color: green;
                border-radius: 100%;

            50% {
                background-color: orange;

            100% {
                background-color: red;

Now, to make the elements move as you move your mouse, we’ll make use of JavaScript.

In the code below, we use an event listener to listen for whenever a user moves their mouse over our webpage. Whenever this event takes place, we use a function to get the x and y coordinates of the mouse. After that, we use the x and y coordinates to move our div elements around as a representative of our cursor:

const cursorSmall = document.querySelector('.small');
const cursorBig = document.querySelector('.big');

const positionElement = (e)=> {
  const mouseY = e.clientY;
  const mouseX = e.clientX; = `translate3d(${mouseX}px, ${mouseY}px, 0)`; = `translate3d(${mouseX}px, ${mouseY}px, 0)`;


window.addEventListener('mousemove', positionElement)

See the complete code alongside the interactive cursor in the below CodePen:

See the Pen CSS Cursors by Samson Omojola (@Caesar222)
on CodePen.

As you can see, we used querySelector to get access to the two div elements on the DOM. Then, we added an event listener to the webpage to listen for and detect when the user moves their mouse.

When this happens, the event listener triggers a positionElement function. In this function, we mapped these coordinates to the div elements whose DOM positions we have selected already.

We move the div elements in correspondence with the x and y coordinates of the mouse using transform and translate3d. transform repositions elements in horizontal and vertical directions, while translate3d repositions elements in 3D space.

As the mouse moves, its x and y values change, transform and translate3d get updated with the help of the event listener, and the position of each div changes in correspondence.

UX and browser compatibility when creating a custom cursor

When creating a custom cursor, you should always keep the user’s best interests in mind. One way to do this is by creating a cursor that best represents or translates the essence of an element.

While custom cursors give your website a nice touch and a unique feel, it is important to not overdo it. Overcustomizing your cursor can frustrate and confuse your users by complicating their experience on your website.

Before you decide to create a custom cursor, you should consider its functionality. For example, will a custom cursor’s features work well on an old browser?

Note that some older browsers do not have the capability to support a lot of new CSS and JavaScript features. If you design certain areas of your website around a custom cursor that uses technologies beyond your users’ browsers, they won’t be able to engage with your website.

Creating a custom cursor with accessibility in mind

As mentioned previously, custom cursors can be helpful for users with impaired mobility and other accessibility requirements. For example, people with low vision may need really large mouse pointers that are easy to track, or mouse pointers with custom colors that make them stand out from various backgrounds.

A mouse can also be programmed to invert the colors of any elements it hovers over. This makes it easy for users to track what they’re reading or seeing on the screen. The text cursor or caret can also be thickened so that users with low vision don’t lose track of where the cursor is on the page while typing.

Large cursors can also benefit users with motor impairment, as they are easier to move and place on elements than small cursors.


In this tutorial, we learned about CSS cursors available out of the box, how to create custom cursors with CSS, how to give your webpage multiple cursors, and how to use animation in CSS and JavaScript to create custom cursors.

Custom cursors can be a great way to draw your users in, keep them engaged, and direct them efficiently if implemented correctly. If you have any further thoughts or questions about creating custom cursors with CSS, let me know in the comments section.

Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.

LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app, mobile app, or website. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web and mobile apps — .

Samson Omojola I'm an experienced software engineer. I love creating applications with responsive, beautiful, intuitive, state-of-the-art designs. I'm skilled in HTML, CSS, JavaScript, Ionic, React, PHP, Laravel, and Flutter.

Leave a Reply