4

I'm trying to create a custom cursor for certain elements of my site, the only issue I'm having is that although it works fine, I can no longer click elements. Anybody know what might be causing this?

http://codepen.io/liamgallagher/pen/MmprwR

$('a').on('click',function(){
  alert('sad');
});

(function() {
  var follower, init, mouseX, mouseY, positionElement, printout, timer;

  follower = document.getElementById('follower');

  printout = document.getElementById('printout');

  mouseX = (function(_this) {
    return function(event) {
      return event.clientX;
    };
  })(this);

  mouseY = (function(_this) {
    return function(event) {
      return event.clientY;
    };
  })(this);

  positionElement = (function(_this) {
    return function(event) {
      var mouse;
      mouse = {
        x: mouseX(event),
        y: mouseY(event)
      };
      follower.style.top = mouse.y + 'px';
      return follower.style.left = mouse.x + 'px';
    };
  })(this);

  timer = false;

  window.onmousemove = init = (function(_this) {
    return function(event) {
      var _event;
      _event = event;
      return timer = setTimeout(function() {
        return positionElement(_event);
      }, 1);
    };
  })(this);

}).call(this);

5 Answers 5

6

Your custom cursor is preventing mouse clicks from reaching the underlying page.

There's no need to hack around with z-indexes or actively hiding/revealing the cursor to solve this; pointer-events exists for this purpose:

#follower {
    pointer-events: none
}

Any pointer (mouse or touch) events will now fall through to whatever is behind your custom cursor. Note that this includes :hover events, so the standard hover cursor will appear on links unless you suppress it; for example:

a:hover {cursor: none} 
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the great answer @DanielBeck - How would I hide the cursor however with pointer-events on?
@Liam, Sure thing, adding that to the answer now.
2

Add z-index: -1 to #follower. A non-static position on #follower gives that element a default z-index when everything else is statically positioned so nothing else has a z-index. That stacking order means when you click, you're just clicking on the #follower element.

$('a').on('click',function(){
  alert('sad');
});

(function() {
  var follower, init, mouseX, mouseY, positionElement, printout, timer;

  follower = document.getElementById('follower');

  printout = document.getElementById('printout');

  mouseX = (function(_this) {
    return function(event) {
      return event.clientX;
    };
  })(this);

  mouseY = (function(_this) {
    return function(event) {
      return event.clientY;
    };
  })(this);

  positionElement = (function(_this) {
    return function(event) {
      var mouse;
      mouse = {
        x: mouseX(event),
        y: mouseY(event)
      };
      follower.style.top = mouse.y + 'px';
      return follower.style.left = mouse.x + 'px';
    };
  })(this);

  timer = false;

  window.onmousemove = init = (function(_this) {
    return function(event) {
      var _event;
      _event = event;
      return timer = setTimeout(function() {
        return positionElement(_event);
      }, 1);
    };
  })(this);

}).call(this);
html {
  cursor: none;
  background: #666;
  height: 5000px;
}
#follower {
  position: fixed;
  top: 50%;
  left: 50%;
  z-index: -1;
}
#follower #circle1 {
  position: absolute;
  -webkit-animation: pulse 2s infinite; /* Chrome, Safari, Opera */
  animation: pulse 2s infinite;
  background: #fff;
  border-radius: 50%;
  height: 0em;
  width: 0em;
  margin-top: 0em;
  margin-left: 0em;
}
#follower #circle2 {
  position: absolute;
  -webkit-animation: pulse 4s infinite; /* Chrome, Safari, Opera */
  animation: pulse 4s infinite;
  background: rgba(200,0,0,0.8);
  border-radius: 50%;
  height: 0em;
  width: 0em;
  margin-top: 0em;
  margin-left: 0em;
}
@-moz-keyframes pulse {
  0% {
    opacity: 0.2;
    height: 1em;
    width: 1em;
    margin-top: -0.5em;
    margin-left: -0.5em;
  }
  50% {
    opacity: 0.9;
    height: 3em;
    width: 3em;
    margin-top: -1.5em;
    margin-left: -1.5em;
  }
  100% {
    opacity: 0.2;
    height: 1em;
    width: 1em;
    margin-top: -0.5em;
    margin-left: -0.5em;
  }
}
@-webkit-keyframes pulse {
  0% {
    opacity: 0.2;
    height: 1em;
    width: 1em;
    margin-top: -0.5em;
    margin-left: -0.5em;
  }
  50% {
    opacity: 0.9;
    height: 3em;
    width: 3em;
    margin-top: -1.5em;
    margin-left: -1.5em;
  }
  100% {
    opacity: 0.2;
    height: 1em;
    width: 1em;
    margin-top: -0.5em;
    margin-left: -0.5em;
  }
}
@-o-keyframes pulse {
  0% {
    opacity: 0.2;
    height: 1em;
    width: 1em;
    margin-top: -0.5em;
    margin-left: -0.5em;
  }
  50% {
    opacity: 0.9;
    height: 3em;
    width: 3em;
    margin-top: -1.5em;
    margin-left: -1.5em;
  }
  100% {
    opacity: 0.2;
    height: 1em;
    width: 1em;
    margin-top: -0.5em;
    margin-left: -0.5em;
  }
}
@keyframes pulse {
  0% {
    opacity: 0.2;
    height: 1em;
    width: 1em;
    margin-top: -0.5em;
    margin-left: -0.5em;
  }
  50% {
    opacity: 0.9;
    height: 3em;
    width: 3em;
    margin-top: -1.5em;
    margin-left: -1.5em;
  }
  100% {
    opacity: 0.2;
    height: 1em;
    width: 1em;
    margin-top: -0.5em;
    margin-left: -0.5em;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="http://www.google.com" target="_blank">Link</a>
<div id="follower">
  <div id="circle1"></div>
  <div id="circle2"></div>
</div>

1 Comment

This is great for the text link @michaelCoker but if I was to use an image in the anchor it puts the cursor behind that
1

If you want to prevent your normal cursor from showing when above the link then you can add the following lines to your script:

  clickElement = (function(_this) {
    return function(event) {
      var mouse;
      mouse = {
        x: mouseX(event),
        y: mouseY(event)
      };

      var followerDisplay = follower.style.display;
      follower.style.display = "none";
      var elementAtCursor = document.elementFromPoint(mouse.x, mouse.y);
      follower.style.display = followerDisplay;
      elementAtCursor.click();
    };
  })(this);

  window.onmouseup = (function(_this) {
    return function(event) {
      var _event;
      _event = event;
      return (timer = setTimeout(function() {
        return clickElement(_event);
      }, 1));
    };
  })(this);

On mouseup the position is obtained, then the follower element is rendered display: none in order to get the element at position using document.elementFromPoint(x, y) then follower gets its display property back.

The downside (or not if it pleases you) is that the animation is restarted.

So in order to keep the animation running you can use visibility instead:

  follower.style.visibility = "hidden";
  var elementAtCursor = document.elementFromPoint(mouse.x, mouse.y);
  follower.style.visibility = 'visible';
  elementAtCursor.click();

Comments

0

This seems a little hacky but it works.

JS

(function() {
  var follower, init, mouseX, mouseY, positionElement, printout, timer;

  follower = document.getElementById('follower');

  printout = document.getElementById('printout');

  mouseX = (function(_this) {
    return function(event) {
      return event.clientX;
    };
  })(this);

  mouseY = (function(_this) {
    return function(event) {
      return event.clientY;
    };
  })(this);

  positionElement = (function(_this) {
    return function(event) {
      var mouse;
      mouse = {
        x: mouseX(event),
        y: mouseY(event)
      };
      follower.style.top = mouse.y + 'px';
      return follower.style.left = mouse.x + 'px';
    };

  })(this);

  $('#follower').on('mousedown', function(){
    // Hide the #follower element
    $(this).hide(); 

    // Set the hover event on anchor tags so this immediately gets called if we're over an anchor tag
    $('a').on('mouseover', function(){
      $(this).click(); // Click the anchor tag
      $('#follower').show(); // Show the #follower element again
    })
  });

  // Unbind the anchor tag mouseover event so we don't click anchor tags by moving the mouse quickly
  $(document).on('mouseover', function() {
    $('a').unbind('mouseover').show();
  })
  
  timer = false;

  window.onmousemove = init = (function(_this) {
    return function(event) {
      var _event;
      _event = event;
      return timer = setTimeout(function() {
        return positionElement(_event);
      }, 1);
    };
  })(this);

}).call(this);

I added this section:

$('#follower').on('mousedown', function(){
    // Hide the #follower element
    $(this).hide(); 

    // Set the hover event on anchor tags so this immediately gets called if we're over an anchor tag
    $('a').on('mouseover', function(){
      $(this).click(); // Click the anchor tag
      $('#follower').show(); // Show the #follower element again
    })
});

// Unbind the anchor tag mouseover event so we don't click anchor tags by moving the mouse quickly
$(document).on('mouseover', function() {      
    $('a').unbind('mouseover').show();
})

Comments

-1

Thats because Link is lower then the circles. So you are actually clicking the circle. Add css z-index lower then the link or however you want to fix but the issue is with z-index.

http://codepen.io/anon/pen/PmpQzg

#follower {
  position: fixed;
  top: 50%;
  left: 50%;
  z-index: -1;
}

1 Comment

Not sure why its down-voted? Problem is identified with demo. @stackoverflow needs to review such down votes :@

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.