<body>
    <div class="headings"><h1>It's Magical</h1>
  <h2>Isn't it?</h2></div>
 
  
  <div id="interactions">
  <button>toggle default Cursor</button>
    <button id="blend">toggle mix-blend-mode</button>
    <button id="ballToggle">Toggle cursor-ball-amount</button>
 
  <input value="yellow" type="color" id="color">
  </div>
  <div id="one" class="cursorHelper"></div>
    <div id="two" class="cursorHelper"></div>
    <div id="three" class="cursorHelper"></div>
    <div id="four" class="cursorHelper"></div>
    <div id="five" class="cursorHelper"></div>
</body>
:root {
  --scale: 1;
    --scaleX: 1;
    --scaleY: 1;
  --br: 25px;
  --width: 50px;
  --height: 50px;
  --posX: -50px; 
  --posY: -50px;
  --cursor: none;
  --color: purple;
  --blendMode: normal;
  --zIndex: -2;
}

*{
    cursor: var(--cursor);
}

body {
  height: 100vh;
  width: 100vw;
  padding: 0;
  margin: 0;
}

.headings {
color: white;
  pointer-events: none;
   user-select: none; 
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  font-family: sans-serif;
  font-size: 2rem;
}


h2 {
  color: lightblue;
}

.cursorHelper {
  transform: translate3d(var(--posX), var(--posY), 0);
  position: fixed;
  top: 0;
  left: 0;
  z-index: var(--zIndex);
  mix-blend-mode: var(--blendMode)
  
}

.cursorHelper::before {
  pointer-events: none;
  width: var(--width);
  height: var(--height);
  position: absolute;
  content: " ";
  background-color: var(--color);
  border-radius: var(--br);
  transition: transform 0.2s, background-color .3s, opacity .3s, border-radius .3s;
  transform: scale(var(--scale));
}

.cursorHelper#one {

  transition: transform .1s ease-out;
}

.cursorHelper#one::before {
  transform: scale(calc(var(--scaleX) * 1), calc(var(--scaleY) * 1));
}

.cursorHelper#two {
  transition: transform .2s ease-out;
  opacity: .8;
}

.cursorHelper#two::before {
  transform: scale(calc(var(--scaleX) * 1.2), calc(var(--scaleY) * 1.2));
}

.cursorHelper#three {
  transition: transform .3s ease-out;
      opacity: .6
}
.cursorHelper#three::before {
  transform: scale(calc(var(--scaleX) * 1.4), calc(var(--scaleY) * 1.4));
}

.cursorHelper#four {
  transition: transform .4s ease-out;
      opacity: .4
}

.cursorHelper#four::before {
  transform: scale(calc(var(--scaleX) * 1.6), calc(var(--scaleY) * 1.6));
}

.cursorHelper#five {
  transition: transform .5s ease-out;
  opacity: .2
}

.cursorHelper#five::before {
  transform: scale(calc(var(--scaleX) * 1.8), calc(var(--scaleY) * 1.8));
}

body.hovering .cursorHelper:not(#one)::before {
  opacity: 0;
}

#interactions {
  right: 25px;
  top: 25px;
  position: absolute;
  display: flex;
  flex-direction: column;
}

#interactions > * {
  margin: .5rem 0;
}

#interactions > input[type="color"] {
    align-self: end;
}



.none {
  display: none;
}
const cursor = document.querySelector(".cursorHelper")
const root = document.querySelector(':root')
const body = document.body

let cursorToggle = false
let isHovering = false
let color = "purple"
let zIndexIsNegative = true
let blendmodeIsOff = true
let baseScale = 1

const applyCursorPos = ({clientX, clientY}) => {
  const x = `${clientX - 25}px`
  const y = `${clientY - 25}px`

  if(!isHovering) {
    
 root.style.setProperty("--posX", x);
 root.style.setProperty("--posY", y);
  }
}

const increaseMouseSize = ({increase}) => {
  root.style.setProperty("--scaleX", increase ? "3" : baseScale);
    root.style.setProperty("--scaleY", increase ? "3" : baseScale);
}

const toggleCursor = () => {
  cursorToggle = !cursorToggle
  root.style.setProperty("--cursor", cursorToggle ? "auto" : "none");
}

cursorHoverState = (e, {hovering}) => { 
  isHovering = hovering
  const rect = e.target.getBoundingClientRect();
  body.classList.toggle("hovering")
  
  root.style.setProperty("--posX", rect.x + (rect.width / 2) - 25 + "px");
    root.style.setProperty("--posY", rect.y + (rect.height / 2) - 25 + "px");
      root.style.setProperty("--color", hovering ? "orange" : color);
        root.style.setProperty("--scaleX", hovering ? (rect.width + 10) / 50 : 1 );
          root.style.setProperty("--scaleY", hovering ? (rect.height + 10) / 50 : 1 );
          root.style.setProperty("--br", hovering ? "0" : "25px")
}

document.body.addEventListener("mousemove", applyCursorPos)

document.body.addEventListener("mousedown", () => {increaseMouseSize({increase: true})})
document.body.addEventListener("mouseup", () => {increaseMouseSize({increase: false})})

document.querySelector("button").addEventListener("click", toggleCursor)

document.querySelectorAll("button, a, input, select").forEach(btn => {
  btn.addEventListener("mouseover", (e) => {cursorHoverState(e, {hovering: true})})
  btn.addEventListener("mouseout", (e) => {cursorHoverState(e, {hovering: false})})
});

document.querySelector("input[type='color']").addEventListener("input", (e) => { 
  color = e.target.value
  root.style.setProperty("--color", color)
})

document.querySelector("#blend").addEventListener("click", () => {
  zIndexIsNegative = !zIndexIsNegative
  blendmodeIsOff = !blendmodeIsOff
  
  root.style.setProperty("--zIndex", zIndexIsNegative ? -2 : 0);
    root.style.setProperty("--blendMode", blendmodeIsOff ? "normal" : "difference")
})

document.querySelector("#ballToggle").addEventListener("click", () => {
  document.querySelectorAll(".cursorHelper:not(#one)").forEach(el => {
    el.classList.toggle("none")
  })
})


// document.querySelector(`input[type="number"]`).addEventListener("change", (e) => {
//   const val = e.target.value
//   baseScale = val
  
//   root.style.setProperty("--scaleX", val);
//     root.style.setProperty("--scaleY", val);
// })
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.