What is the difference between screenX/Y, clientX/Y and pageX/Y? - javascript

What is the difference between screenX/Y, clientX/Y and pageX/Y?
Also for iPad Safari, are the calculations similar as on desktop—OR there is some difference because of viewport?
It would be great if you could point me to an example.

Here's a picture explaining the difference between pageY and clientY and screenY.
Same for pageX and clientX and screenX, respectively.
pageX/Y coordinates are relative to the top left corner of the whole rendered page (including parts hidden by scrolling),
while clientX/Y coordinates are relative to the top left corner of the visible part of the page, "seen" through browser window.
screenX/Y are relative to the physical screen.
See Demo
or try this snippet:
document.addEventListener('DOMContentLoaded', _ => {
const info = document.getElementById('info');
const updateInfo = event => {
const { clientX, clientY, pageX, pageY } = event;
info.innerHTML = `clientX: ${clientX} clientY: ${clientY}<br /> pageX: ${pageX} pageY: ${pageY}`;
};
document.addEventListener('mouseover', updateInfo);
document.addEventListener('mousemove', updateInfo);
});
body {
border: 1px solid red;
min-height: 10000px;
margin: 10px;
}
#info {
border: 1px solid blue;
position: fixed;
top: 80px;
left: 40px;
}
<h3>Move the mouse around and scroll to see the values of clientX/Y and pageX/Y</h3>
<div id="info"></div>
Note: You'll probably never need screenX/Y

In JavaScript:
pageX, pageY, screenX, screenY, clientX, and clientY returns a number which indicates the number of logical “CSS pixels” an event point is from the reference point. The event point is where the user clicked and the reference point is a point in the upper left. These properties return the horizontal and vertical distance of the event point from that reference point.
pageX and pageY:
Relative to the top left of the fully rendered content area in the browser. This reference point is below the URL bar and back button in the upper left. This point could be anywhere in the browser window and can actually change location if there are embedded scrollable pages embedded within pages and the user moves a scrollbar.
screenX and screenY:
Relative to the top left of the physical screen/monitor, this reference point only moves if you increase or decrease the number of monitors or the monitor resolution.
clientX and clientY:
Relative to the upper left edge of the content area (the viewport) of the browser window. This point does not move even if the user moves a scrollbar from within the browser.
For a visual on which browsers support which properties:
http://www.quirksmode.org/dom/w3c_cssom.html#t03
<script>
function showCoordinates(event){
var x = event.clientX;
var y = event.clientY;
alert(`X coordinates: ${x}, Y coordinates: ${y}`);
}
</script>
<p onmousedown="showCoordinates(event)">
Click this paragraph, and an alert box will show the x
and y coordinates of the mouse relative to the viewport
</p>

pageX/Y gives the coordinates relative to the <html> element in CSS pixels.
clientX/Y gives the coordinates relative to the viewport in CSS pixels.
screenX/Y gives the coordinates relative to the screen in device pixels.
Regarding your last question if calculations are similar on desktop and mobile browsers... For a better understanding - on mobile browsers - we need to differentiate two new concept: the layout viewport and visual viewport. The visual viewport is the part of the page that's currently shown onscreen. The layout viewport is synonym for a full page rendered on a desktop browser (with all the elements that are not visible on the current viewport).
On mobile browsers the pageX and pageY are still relative to the page in CSS pixels so you can obtain the mouse coordinates relative to the document page. On the other hand clientX and clientY define the mouse coordinates in relation to the visual viewport.
There is another stackoverflow thread here regarding the differences between the visual viewport and layout viewport : Difference between visual viewport and layout viewport?
Another good resource: http://www.quirksmode.org/mobile/viewports2.html

I don't like and understand things, which can be explained visually, by words.

What helped me was to add an event directly to this page and click around for myself! Open up your console in developer tools/Firebug etc and paste this:
document.addEventListener('click', function(e) {
console.log(
'page: ' + e.pageX + ',' + e.pageY,
'client: ' + e.clientX + ',' + e.clientY,
'screen: ' + e.screenX + ',' + e.screenY)
}, false);
Click anywhere
With this snippet, you can track your click position as you scroll, move the browser window, etc.
Notice that pageX/Y and clientX/Y are the same when you're scrolled all the way to the top!

The difference between those will depend largely on what browser you are currently referring to. Each one implements these properties differently, or not at all. Quirksmode has great documentation regarding browser differences in regards to W3C standards like the DOM and JavaScript Events.

Comparison with offsetX/Y
Other interesting properties are offsetX/Y (offset between the mouse and the border of the clicked element/node). Here's a fuller picture:
Source

clientX/Y refers to relative screen coordinates, for instance if your web-page is long enough then clientX/Y gives clicked point's coordinates location in terms of its actual pixel position while ScreenX/Y gives the ordinates in reference to start of page.

Related

How to calculate left and top for div with position absolute when click

I have some items with "click" event. When I click on this items I have to show modal in the place of the click. This modal has position absolute.
I try to get event.pageX and event.pageY
let style = 'top: ' + event.pageX+ 'px; left: ' + event.pageY + 'px;';
but my modal shows very far (look at screen)
http://joxi.ru/brRa073u7J73vA
You can use clientX/clientY event's properties to get the place of the click
You're probably looking for clientX and clientY, and not pageX and pageY. Also, notice that you must put position: absolute on the modal you're trying to place so it'll work as you're expecting it to (and if you're not too familiar with positioning you should definitely read about it - it's not as simple as it sounds).
pageX and pageY:
Relative to the top left of the fully rendered content area in the browser [...] This point could be anywhere in the browser window and can actually change location if there are embedded scrollable pages embedded within pages and the user moves a scrollbar.
screenX and screenY:
Relative to the top left of the physical screen/monitor.
clientX and clientY:
Relative to the upper left edge of the content area (the viewport) of the browser window. This point does not move even if the user moves a scrollbar from within the browser.
Read more:
What is the difference between screenX/Y, clientX/Y and pageX/Y?
Here's a working example:
document.addEventListener("click", e => {
console.log(e.clientX, e.clientY);
let modal = document.getElementById("modal");
modal.style.top = e.clientY+"px";
modal.style.left = e.clientX+"px";
});
#modal {
position: absolute;
width: 100px;
height: 200px;
background: blue;
}
<div id="modal"></div>

Position tooltip above mouse when room in viewport, otherwise below mouse

I am creating a tooltip and am having some problems with positioning it.
The tooltip is set to position: absolute, and I have a handler for mouse events that modifies it's top and left CSS depending on the pageX and pageY.
Now, I know I can just set the top to pageY and left to pageX. That will make the tooltip pop up to the bottom-right. I'm trying to orient it where it pops up on the top-right when there is room, but if it would be out of the viewport on the Y-axis, drop to the bottom-right position again.
At the moment, I'm stuck trying to get the tooltip to show to the top-right of the mouse. I don't even know where to begin detecting if it would be in the viewport. Can anyone point me in the right direction?
$('p').on('mouseenter', function(e) {
$(tt).css('top', e.pageY - $(tt).css('height'));
$(tt).css('left', e.pageX);
$(tt).appendTo('body');
}).on('mousemove', function(e) {
$(tt).css('top', e.pageY - $(tt).css('height'));
$(tt).css('left', e.pageX);
}).on('mouseleave', function(e) {
$(tt).detach();
});
Example on JSFiddle
There are many different ways to handle tooltips, especially when using jQuery. This method probably would not have been my first choice. However, the following changes should work how you intended.
var tt = document.createElement('div');
tt.id = "tt";
$('p').on('mouseenter', function(e) {
var curPos = $( this ).offset().top - $( window ).scrollTop();
var inView = (curPos < 250) ? 0 : 250;
$(tt).css('top', e.pageY - inView);
$(tt).css('left', e.pageX);
$(tt).append($( this ).attr("data-myId"));
$(tt).appendTo('body');
}).on('mousemove', function(e) {
$(tt).css('top', e.pageY - $(tt).css('height'));
$(tt).css('left', e.pageX);
}).on('mouseleave', function(e) {
$(tt).empty($( this ).attr("data-myId"));
$(tt).detach();
});
Full changes in JSFiddle.
I am taking advantage of jQuery's offset() and scrollTop() methods to estimate the position of the current element within the viewable area of the document.
According to jQuery's API documentation, the .offset() method
allows us to retrieve the current position of an element relative to
the document. The documentation also states that the vertical
scroll position (.scrollTop()) is the same as the number of pixels that are hidden
from view above the scrollable area.
We use both of these methods to our advantage and subtract the number of pixels above the scrollable area from the current position of the element relative to the document. One important thing to note is that the offset method returns an object with the properties top and left.
var curPos = $( this ).offset().top - $( window ).scrollTop();
Since you had the #tt id set to a static 250px height, we can check if the current element position relative to the viewable portion of the window is less than 250. If it is, then we subtract nothing and let the tool tip sit below the mouse position. If it is greater than 250 then we subtract 250px and the tool tip will be above the current mouse position.
I am not sure how you were intending to pull in the content for the tool tips, but I also added $(tt).append($( this ).attr("data-myId")); to use the data-myId value as the tool tip content and $(tt).empty($( this ).attr("data-myId")); to clear it on mouseleave. I hope this helps!

What is the difference between pageX/Y clientX/Y screenX/Y in Javascript? [duplicate]

This question already has answers here:
What is the difference between screenX/Y, clientX/Y and pageX/Y?
(8 answers)
Closed 8 years ago.
An example with some visual cue would be really helpful.
The visual cues represents:
Screen → the full screen of the monitor (screenX/Y)
Position will always be relative to the physical screen's viewport.
Client → the client viewport of the browser (clientX/Y)
If you click in the left top corner the value will always be (0,0) independent on scroll position.
Document → the complete document/page (pageX/Y)
Note that pageX/pageY on the UIEvent object are not standardized.
All values are in pixels.
CLIENT → The Browser window
clientX clientY = values (px) of the mouse position relative to the Browser's viewport boundaries.
Tip:
Even if you scroll the Document, the values are always the same
PAGE → The Whole Document
pageX pageY = values (px) of the mouse position relative to the Document most-top/left "sides".
Tip:
If you scroll the Document (i.e) vertically, pageY value changes cause it's the new mouse Top Position inside your Document.
Also it's worth noting that:
event.pageY - event.clientY === document.documentElement.scrollTop ( or jQuery's $("html, body").scrollTop() )
SCREEN → Your Screen
screenX and screenY are the values (px) of the current mouse position relative to the physical screen.
Mouse coordinates example:
const EL = (sel, par) => (par||document).querySelector(sel);
EL("body").addEventListener("mousemove", (evt) => {
["client","page","screen"].forEach(mod => {
EL(`#${mod}-x`).textContent = evt[mod+"X"];
EL(`#${mod}-y`).textContent = evt[mod+"Y"];
});
});
* {margin:0; box-sizing: border-box;}
body{
height: 300vh; /* just to force some scrollbars */
font: 14px/1.5 monospace;
}
table{
position:fixed;
border-spacing:0;
border-collapse: collapse;
}
table td{
vertical-align:bottom;
border:1px solid #ddd;
padding:3px 10px;
}
table tr:first-child{
background:#ddd;
}
<table>
<tr><td>Mouse position inside:</td><td>X</td><td>Y</td></tr>
<tr><td><b>screen</b> display</td><td id="screen-x"></td><td id="screen-y"></td></tr>
<tr><td><b>client</b> viewport</td><td id="client-x"></td><td id="client-y"></td></tr>
<tr><td><b>page</b> document (scroll to see diff))</td><td id="page-x"></td><td id="page-y"></td></tr>
</table>
Additional read for Mouse XY coordinates depending on parent / child positions
Generally, the differences are:
page x/y: the x or y coordinate as relative the to the fully rendered page (i.e., it considers the entire height and width of the page/document, not just what is currently being shown on screen)
screen x/y: the x or y coordinate as relative to the physical screen.
client x/y: the x or y coordinate as relative to the client (browser) window (or iframe inside the window.
Here is a page where you can test the differences dynamically.

Is my understanding of document and viewport with regards to mouse position in javascript correct?

Based on answers from a previous question, both refer to mouse positions (x and y coordinates).
relative to the document and
relative to the viewport.
I have read through an article on QuirksMode, however I think I may be missing something. I have put together these two diagrams to help me in my understanding. Is my analysis correct?
Now scroll the document 250px...
Your analysis is correct (and those are very nice diagrams!)
However regarding your other post, they're a bit more information than is necessary.
You just need to understand that there is a document and viewport. The document is stationary and the viewport moves with you (and has a scroll offset).
In principle, you could place your dialog window relative to either of these. Let's pretend the dialog is a simple division element:
<body>
<button id="save">Save</button>
<div id="dialog" style="position:absolute;">Are you sure?</div>
</body>
And let's say you want to position that element relative to your button when clicked. You could use the document:
<script>
document.getElementById("save").onclick = function(e) {
var dialog = document.getElementById("dialog");
dialog.style.top = e.pageY + "px";
/*
pageY gives the position of the mouse relative to the
document, when this event occurred.
*/
};
</script>
Or you could use the viewport:
<script>
document.getElementById("save").onclick = function(e) {
var dialog = document.getElementById("dialog");
dialog.style.top = e.clientY + window.pageYOffset + "px";
/*
clientY gives the position of the mouse relative to
the viewport, when this event occurred. And pageYOffset
is the distance the user has scrolled.
*/
};
</script>
You could even use the button itself. This has the added benefit of giving you a consistent position, regardless of where exactly the user clicked:
<script>
document.getElementById("save").onclick = function(e) {
var dialog = document.getElementById("dialog");
dialog.style.top = document.getElementById("save").offsetTop + "px";
/*
offsetTop gives the position of the button, relative to its nearest
positioned ancestor. If the element is deeply nested, you may need
to do additional calculations. (jQuery's "offset" method will do this
for you).
*/
};
</script>
To apply that last method when you're using jQuery's dialog class, you can simply do this:
<script>
$("#save").click(function(e) {
$("#dialog").dialog({
position: {
my: "top",
at: "bottom",
of: $("#save")
}
/*
See this: http://docs.jquery.com/UI/API/1.8/Position
*/
});
});
</script>

How to know when an element will be off screen?

I am writing a simple script that displays a dialog box when a user hovers over a profile picture. It dynamically determines the profile pics location on the page and then places itself to the left of it and about 100px above it. This part is working fine.
My issue arises when a profile pic is at the top of the screen and a user mouses over it. The dialog will appear but the top portion of it will be above the fold (i.e. not in the current browser window). Naturally this is not good usability and I would like it to appear on the screen.
My question is how do I know when a dialog will be off screen so I can recalculate its position on the page?
I saw this question which seems like the same as mine but unfortunately no actual solution was provided other then to link to a jQuery plugin. I am using Prototype.
Prototype already provides positions with Element.viewportOffset().
Edit, as Mathew points out document.viewport gives the rest of the information. For example,
var dialogtop = dialog.viewportOffset().top;
if (dialogtop < 0) {
// above top of screen
}
elseif (dialogtop + dialog.getHeight > document.viewport.getHeight()) {
// below bottom of screen
}
You'll want to find the profile pic's position relative to the document (here's a good article on how, though I suspect Prototype's Element.Offset already handles this), then compare it to the body's scrollTop property to see if it's close enough to the top that it needs to have its dialog repositioned.
I am familiar with this problem, however, last time I was able to use a library (Seadragon) to get the screen dimensions and mouse position. I was also working with a fixed size overlay so no code to share with you other than general approach.
For my pop up box I decided to use the event mouse position rather than location of the div on the page. I then compared the mouse position to the known screen size, which I determined on start or resize.
From How do I get the size of the browser window using Prototype.js?
var viewport = document.viewport.getDimensions(); // Gets the viewport as an object literal
var width = viewport.width; // Usable window width
var height = viewport.height; // Usable window height
In Prototype you can also get the mouse coordinates:
function getcords(e){
mouseX = Event.pointerX(e);
mouseY = Event.pointerY(e);
//for testing put the mouse cords in a div for testing purposes
$('debug').innerHTML = 'mouseX:' + mouseX + '-- mouseY:' + mouseY;
}
Source : http://remorse.nl/2008/06/mouse_coordinates_with_prototype/

Categories

Resources