<div id="rjs_cursor" class="rjs-cursor">
  <div class="rjs-cursor-icon"></div>
</div>

<div class="page-content">
  <h1>Custom cursor with CSS</h1>
  
  <p>
    <a href="https://ralphjsmit.com/animated-custom-cursor" rel="noopener">Read the article</a>
  </p>

    <p>
    <!-- start slipsum code -->
    Well, the way they make shows is, they make one show. That show's called a pilot. Then they show that show to the people who make shows, and on the strength of that one show they decide if they're going to make more shows. <a href="https://ralphjsmit.com/>">Some pilots</a> get picked and become television programs. Some don't, become nothing. She starred in one of the ones that became nothing.
  <!-- end slipsum code -->
</p>   
  <form action="#form">
    <p>
      <label for="text">Dummy form</label><br>
      <input type="text" id="text">
    </p>
    <button>Send</button>
  </form>
  
  <br>
  
  <div class="mycustomclass" style="display: inline-block; height: 40px; background-color: orange; padding: 6px; line-height: 40px; color: white; margin: 6px; border-radius: 8px;">Custom clickable div</div>
  
</div>
.rjs-cursor {
  width: 12px;
  height: 12px;
  position: fixed;      /* Fixed position.. */
  top: 0;               /* at the top left.. */
  left: 0;
  z-index: 999999;      /* above everything else. */
  pointer-events: none; /* Cant't be clicked. */
  transition: none;     /* Cursor is always accurate */
  opacity: 0; /* Hidden by default */
  transform: translate(-50%; -50%);
}

.rjs-cursor-icon {      /* Styling for the visible part */
  width: 100%;
  height: 100%;
  border-radius: 100%;  /* Circle */
  background-color: #ffe3d3; /* Backup value */
  transition: all 0.2s ease; 
  transform-origin: 50% 50%;
}

.rjs-cursor.rjs_cursor_visible { opacity: 1; }
.rjs-cursor.rjs_cursor_hidden { opacity: 0; }

/* Display the cursors at the correct time */
* { cursor: none; }

@media (pointer: none), (pointer: coarse) {
    #rjs_cursor, #rjs_cursor .rjs-cursor-icon { display: none !important; visibility: hidden; opacity: 0; }

    * { cursor: auto !important; }
}


/* Hover effects */
.rjs-cursor.rjs_cursor_hover .rjs-cursor-icon { transform: scale(2); }





/* The body element is required to fill the complete browser. This will be the case on almost every website that has content. Otherwise you could add this as a fallback */

body { min-width: 100vw; min-height: 100vh; margin: 0; } */
var rjs_cursor =  document.getElementById("rjs_cursor"); //Getting the cursor
var body =  document.querySelector("body"); //Get the body element

//Functions for showing and hiding the cursor
//They are referenced the 
 function rjs_show_cursor(e) { //Function to show/hide the cursor
    if(rjs_cursor.classList.contains('rjs_cursor_hidden')) {
        rjs_cursor.classList.remove('rjs_cursor_hidden');
    }
    rjs_cursor.classList.add('rjs_cursor_visible');
}

function rjs_hide_cursor(e) {    if(rjs_cursor.classList.contains('rjs_cursor_visible')) {
    rjs_cursor.classList.remove('rjs_cursor_visible');
    }
    rjs_cursor.classList.add('rjs_cursor_hidden');
}


function rjs_mousemove(e) { //Function to correctly position the cursor
    rjs_show_cursor(); //Toggle show/hide
  
    var rjs_cursor_width = rjs_cursor.offsetWidth * 0.5;
    var rjs_cursor_height = rjs_cursor.offsetHeight * 0.5;

    var rjs_cursor_x = e.clientX - rjs_cursor_width; //x-coordinate
    var rjs_cursor_y = e.clientY - rjs_cursor_height; //y-coordinate
    var rjs_cursor_pos = `translate(${rjs_cursor_x}px, ${rjs_cursor_y}px)`;
    rjs_cursor.style.transform = rjs_cursor_pos;
}


//Eventlisteners
window.addEventListener('mousemove', rjs_mousemove); //Attach an event listener
body.addEventListener('mouseleave', rjs_hide_cursor);



//Hover behaviour
function rjs_hover_cursor(e) { rjs_cursor.classList.add('rjs_cursor_hover'); }
function rjs_unhover_cursor(e) { rjs_cursor.classList.remove('rjs_cursor_hover'); }


document.querySelectorAll('a').forEach(item => {
    item.addEventListener('mouseover', rjs_hover_cursor);
    item.addEventListener('mouseleave', rjs_unhover_cursor);
})

document.querySelectorAll('input').forEach(item => { //Input tags
    item.addEventListener('mouseover', rjs_hover_cursor);
    item.addEventListener('mouseleave', rjs_unhover_cursor);
})

document.querySelectorAll('button').forEach(item => { //Input tags
    item.addEventListener('mouseover', rjs_hover_cursor);
    item.addEventListener('mouseleave', rjs_unhover_cursor);
})

document.querySelectorAll('.mycustomclass').forEach(item => { //A custom class
    item.addEventListener('mouseover', rjs_hover_cursor);
    item.addEventListener('mouseleave', rjs_unhover_cursor);
})



External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.