Getting the Mouse Click Position

by kirupa   |   1 January 2013

For all sorts of interactive doo-dads you will be creating, chances are you will be making heavy use of the mouse (or another pointing device like a stylus or finger). Something you may find yourself needing to do is figuring out the exact position of the click.

Let's look at an example where knowing the exact click position is important:

Click anywhere inside the gray box to see the red circle move to the point of your click.

In this tutorial, I will explain the magic behind figuring out the exact pixel coordinates of where a click occurred. While the words "mouse" and "click" will appear often, just know that everything I show here works on a touch device where a stylus or your finger is the pointing thing!

A Worthy (But Incomplete) Attempt

A great way to learn is by understanding why something doesn't work the way it should. In that thread, let's start by looking at a seemingly fine approach that seems like it should give us the exact position of the click.

What we want to do is figure out the exact click position when you click anywhere inside the yellow container:

click area

First, we have the event listener setup to listen for a click event:

yellowContainer.addEventListener("click", getClickPosition, false);

When the click happens, we have an event handler that will react to that click:

function getClickPosition(e) {
	var xPosition = e.clientX;
	var yPosition = e.clientY;
}

If You Are Not Familiar With Event Handling

If any of this event handling jibberish is confusing or unfamiliar, you should first check out my JavaScript Events tutorial before proceeding further. It is a quick read, and it will help the rest of this tutorial make a lot more sense!

Notice what this event handler contains. It contains two variables whose values are the contents of our event object's clientX and clientY properties. These properties return the X and Y position of the click. That is their documented behavior, and that is what they actually do. Sounds exactly like what we are looking for, doesn't it?

The problem is this. The X and Y position returned by clientX and clientY is relative to the element you clicked on:

relative position

It is neither global nor relative to the browser, so the value you get is only partially accurate for what you are trying to do. You want the X and Y position based on the top-left (aka the starting position) corner of your document. It is this value that gives you the exact position of your click. It is this value you will need when using the position for doing clever things like moving an element to the point of the click.

The solution is pretty simple. What we need is to do some more calculations to make our partially accurate answer fully correct!

The Full Solution

The full solution involves combining the values returned from clientX and clientY that you saw earlier with the positions of every element in the DOM going up to your window object. That sounds complicated, but it really isn't.

 The code for correctly getting the click position looks as follows:

// helper function to get an element's exact position
function getPosition(el) {
  var xPosition = 0;
  var yPosition = 0;

  while (el) {
    if (el.tagName == "BODY") {
      // deal with browser quirks with body/window/document and page scroll
      var xScrollPos = el.scrollLeft || document.documentElement.scrollLeft;
      var yScrollPos = el.scrollTop || document.documentElement.scrollTop;

      xPosition += (el.offsetLeft - xScrollPos + el.clientLeft);
      yPosition += (el.offsetTop - yScrollPos + el.clientTop);
    } else {
      xPosition += (el.offsetLeft - el.scrollLeft + el.clientLeft);
      yPosition += (el.offsetTop - el.scrollTop + el.clientTop);
    }

    el = el.offsetParent;
  }
  return {
    x: xPosition,
    y: yPosition
  };
}

To get the position of all the elements between what you clicked on and the document, you have the getPosition function. This function provides you with the additional pieces of information needed to make your existing calculations involving clientX and clientY complete. All you need to do is pass in the element you are starting your measurement from. Inside an event handler, that element can be accessed by the currentTarget property.

Now, I am not going to explain in this tutorial how getPosition works or the logic behind why the code does what it does. The reason is (besides me being horrifically lazy), you can see my full explanation in the Get an Element's Position Using JavaScript tutorial instead. The getPosition function I used here was stolen from that tutorial, and it is a good read if you want to understand more about how positions in HTML can be calculated.

Conclusion

Well, that is all there is to this little tutorial. Getting the click position of something seems easy, but as you saw, it involves a lot of interesting factors that you need to take into account.

Getting Help

If you have questions, need some assistance on this topic, or just want to chat - post in the comments below or drop by our friendly forums (where you have a lot more formatting options) and post your question. There are a lot of knowledgeable and witty people who would be happy to help you out

Share

Did you enjoy reading this and found it useful? If so, please share it with your friends:

If you didn't like it, I always like to hear how I can do better next time. Please feel free to contact me directly via e-mail, facebook, or twitter.

Brought to you by...

Kirupa Chinnathambi
I like to talk a lot - A WHOLE LOT. When I'm not talking, I've been known to write the occasional English word. You can learn more about me by going here.

Add Your Comment (or post on the Forums)

blog comments powered by Disqus

Awesome and high-performance web hosting!
BACK TO TOP
new books - yay!!!