I need to calculate the offsetRight of a DOM object. I already have some rather simple code for getting the offsetLeft, but there is no javascript offsetRight property. If I add the offsetLeft and offsetWidth, will that work? Or is there a better way?
function getOffsetLeft(obj)
{
if(obj == null)
return 0;
var offsetLeft = 0;
var开发者_运维百科 tmp = obj;
while(tmp != null)
{
offsetLeft += tmp.offsetLeft;
tmp = tmp.offsetParent;
}
return offsetLeft;
}
function getOffsetRight(obj)
{
if (obj == null)
return 0;
var offsetRight = 0;
var tmp = obj;
while (tmp != null)
{
offsetRight += tmp.offsetLeft + tmp.offsetWidth;
tmp = tmp.offsetParent;
}
return offsetRight;
}
Cannot be more simpler than this:
let offsetright = window.innerWidth - obj.offsetLeft - obj.offsetWidth
UPDATED POST TO CLARIFY SOME GOTCHAS:
// Assuming these variables:
const elem = document.querySelector('div'),
body = document.body,
html = document.documentElement;
Here are several approaches:
/* Leveraging the viewport AND accounting for possible overflow to the right */
const offsetRight = body.clientWidth - elem.getBoundingClientRect().right
// OR
const offsetRight = body.scrollWidth - elem.getBoundingClientRect().right
// OR
const offsetRight = html.scrollWidth - elem.getBoundingClientRect().right
OR
/*
* Likely the safest option:
* Doesn't depend on the viewport
* Accounts for overflow to the right
* Works even if the user is scrolled to the right some
* NOTE: This ends at the <html> element,
* but you may want to modify the code to end at the <body>
*/
const getOffsetRight = e => {
let left = e.offsetWidth + e.offsetLeft;
const traverse = eRef => {
eRef = eRef.offsetParent; // `.offsetParent` is faster than `.parentElement`
if (eRef) {
left += eRef.offsetLeft;
traverse(eRef);
}
};
traverse(e);
return html.scrollWidth - left;
};
const offsetRight = getOffsetRight(elem);
Import considerations:
- Are you using
box-sizing: border-box;
for all your elements? - Is there
margin-left
set on the<body>
or<html>
elements you need to account for? - Does the
<body>
have a fixed width but centered such as withmargin: 0 auto;
Those things will help determine which method to use, and if you want to modify the CSS and/or the JavaScript to account for those use cases.
ORIGINAL POST:
A few choices:
If you want "offsetRight" relative to the viewport, use
element.getBoundingClientRect().right;
Your example is good simply subracting the parent width from the element's width + offsetLeft.
Lastly, to be relative to the document, and to speed up traversing (offsetParent):
In this example, I'm positioning a pseudo dropdown element below the referenced element, but because I'm avoiding some tricky z-index issues and want to have the element be referenced from the right and expand out left, I had to append it to the body element, and the get the "offsetRight" from the original parent.
... // Set helper defaults dropdownElem.style.left = 'auto'; dropdownElem.style.zIndex = '10'; // Get the elem and its offsetParent let elem = dropdownElemContainer; let elemOffsetParent = elem.offsetParent; // Cache widths let elemWidth = elem.offsetWidth; let elemOffsetParentWidth = 0; // Set the initial offsets let top = elem.offsetHeight; // Because I want to visually append the elem at the bottom of the referenced bottom let right = 0; // Loop up the DOM getting the offsetParent elements so you don't have to traverse the entire ancestor tree while (elemOffsetParent) { top += elem.offsetTop; elemOffsetParentWidth = elemOffsetParent.offsetWidth; right += elemOffsetParentWidth - (elem.offsetLeft + elemWidth); // Most important line like your own example // Move up the DOM elem = elemOffsetParent; elemOffsetParent = elemOffsetParent.offsetParent; elemWidth = elemOffsetParentWidth; } // Set the position and show the elem dropdownElem.style.top = top + 'px'; dropdownElem.style.right = right + 'px'; dropdownElem.style.display = 'block';
//Object references
function getObject(id) {
var object = null;
if (document.layers) {
object = document.layers[id];
} else if (document.all) {
object = document.all[id];
} else if (document.getElementById) {
object = document.getElementById(id);
}
return object;
}
//Get pixel dimensions of screen
function getDimensions(){
var winW = 630, winH = 460;
if (document.body && document.body.offsetWidth) {
winW = document.body.offsetWidth;
winH = document.body.offsetHeight;
}
if (document.compatMode=='CSS1Compat' && document.documentElement && document.documentElement.offsetWidth ) {
winW = document.documentElement.offsetWidth;
winH = document.documentElement.offsetHeight;
}
if (window.innerWidth && window.innerHeight) {
winW = window.innerWidth;
winH = window.innerHeight;
}
return{"width":winW, "height":winH}
}
//Get the location of element
function getOffsetRight(elem){
element=getObject(elem)
var width = element.offsetWidth
var right = 0;
while (element.offsetParent) {
right += element.offsetLeft;
element = element.offsetParent;
}
right += element.offsetLeft;
right = getDimensions()["width"]-right
right -= width
return right
}
This is not bullet-proof but you can usually get the "offsetRight" by calling: getOffsetRight("[object.id]")
If you are interested in using some Js library then try the following functionality of prototype js http://api.prototypejs.org/dom/element/offset/
精彩评论