Andrew
Andrew

Reputation: 6504

MouseEvent.clientX and MouseEvent.clientY Unexpected Results With CSS Scale Transform

$('body').on('mousemove', function (ev) {
    $('span').text(`x: ${ev.clientX}, y: ${ev.clientY}`)
})
body {
  padding: 0;
  margin: 0;
}

div {
  display: inline-block;
  width: 100px;
  height: 100px;
  background: #333;
  transform: scale(2, 2);
}

span {
  position: absolute;
  left: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="my-div"></div>
<span id="my-span"></span>

I was just wondering why the scaled div returns x and y MouseEvent coordinates in the range from 0 to 150 instead of from 0 to 200? The scale property is set to 2, so I thought it would be the second range instead of the first. Could someone explain? Here's a link to the js fiddle page.

I noticed a lot of similar questions on Stackoverflow, so this might be a duplicate. However, I couldn't find anything that specifically asked this question about pixels, coordinates, and the scale transformation in CSS. I may have missed something, though...

Thanks!

Upvotes: 1

Views: 1152

Answers (2)

Temani Afif
Temani Afif

Reputation: 272582

because transform-origin is center by default so half the div is outside the screen from the top/left.

Either update the transform-origin:

$('body').on('mousemove', function (ev) {
    $('span').text(`x: ${ev.clientX}, y: ${ev.clientY}`)
})
body {
  padding: 0;
  margin: 0;
}

div {
  display: inline-block;
  width: 100px;
  height: 100px;
  background: #333;
  transform: scale(2, 2);
  transform-origin:0 0;
}

span {
  position: absolute;
  left: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="my-div"></div>
<span id="my-span"></span>

Or add some margin:

$('body').on('mousemove', function (ev) {
    $('span').text(`x: ${ev.clientX}, y: ${ev.clientY}`)
})
body {
  padding: 0;
  margin: 0;
}

div {
  display: inline-block;
  width: 100px;
  height: 100px;
  background: #333;
  transform: scale(2, 2);
  margin:50px;
}

span {
  position: absolute;
  left: 300px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="my-div"></div>
<span id="my-span"></span>

Upvotes: 2

Matthew Adams
Matthew Adams

Reputation: 10116

The div is scaled relative to its center, so part of it ends up being off screen. (One way to notice this: add a border to the div and see that it doesn't go all the way around.)

Try using transform-origin: top left; on the div - I think that will do what you expect.

Upvotes: 1

Related Questions