Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the actual values for left/right/top/bottom of an absolutely positioned element?

(This seems like a simple question that would have been asked before, but if it has I can't find it, though there are lots of similar ones that don't answer what I want.)

In Firefox (24.0), this code gives me what I want - the relevant number of pixels:

jQuery('selector').css('right')

In Chrome (34.0.1847.137 m), it only gives pixels for left/top but returns auto for right/bottom.

There are various questions on SO explaining that this is the expected behaviour of .css, but I cannot find anything that explains how to get my desired behaviour - i.e. give me calculated pixel values for all four values.

Do JS or jQuery have any way to directly get these four values, that works consistently in all browsers/scenarios? (Or do I have to resort to ugly manual calculations?)

Clarification:
I need values that are equivalent to the .css('right') values that Firefox returns - which is the distance between the right-edges of the current and parent element. This is not the same as viewport-relative left+width definitions which some functions return.

i.e. the logged values here should be numerically the same:

elem = jQuery('selector')
rect = someFunction( elem[0] );
console.log([ elem.css('left') , rect.left ]);
console.log([ elem.css('right') , rect.right ]);
console.log([ elem.css('top') , rect.top ]);
console.log([ elem.css('bottom') , rect.bottom ]);

Unless I'm misreading the other answers, only kalley's getRelativeClientRect answer meets this criteria.

like image 911
Peter Boughton Avatar asked May 27 '14 14:05

Peter Boughton


3 Answers

you can use getBoundingClientRect. It will take into account any transforms as well, if you are using them.

You'd need to call it like jQuery('selector')[0].getBoundingClientRect(). Or use vanilla javascript like document.querySelector('selector').getBoundingClientRect(), which will return a single element or document.querySelectorAll('selector')[index].getBoundingClientRect().

To summarize, in a slightly more readable format:

  • jQuery('selector')[0].getBoundingClientRect()
  • document.querySelector('selector').getBoundingClientRect()
  • document.querySelectorAll('selector')[index].getBoundingClientRect()

or replace the QS calls with older ones like getElementById, etc.

Here's a function you could use if you wanted to get it relative to it's parent:

function getRelativeClientRect(el) {
  var rect = el.getBoundingClientRect(),
      parentRect = el.offsetParent.getBoundingClientRect();
  return {
    bottom: parentRect.bottom - rect.bottom,
    height: rect.height,
    left: rect.left - parentRect.left,
    right: parentRect.right - rect.right,
    top: rect.top - parentRect.top,
    width: rect.width
  };
}
like image 138
kalley Avatar answered Sep 18 '22 16:09

kalley


There is a built-in way to do this in Javascript without JQUERY. There are two special ones I'll show you, one is JS and CSS, other is just JS.

element.style.left; //Gives you distance from left edge of your viewport.
element.style.top + "px"; //Gives you distance in pixels from top edge
element.style.right; //etc.


//There is also the way of Offset. You do not need CSS at all for this.
//Of course, Jquery has its own way of doing this, but I'll show JS-only
element.offsetTop; //Gives distance from top of viewport to top of element
element.offsetLeft; //Gives distance from left of viewport to left of element
//etc.

As always, there are many more ways to do this with and without Jquery. I prefer not using Jquery at all (despite the fact that it is awesome), and I know others prefer not using Jquery too. If you want to use Jquery, I'd recommend using the Jquery way like @farincz did. If not, this way or getBoundingClientRect is better. Best thing about using .style.top or .style.left is that you can not only get the actual values for left/right/top/bottom, but you can also set them. This is great for stuff like drag-and-drop.

like image 28
Cannicide Avatar answered Sep 18 '22 16:09

Cannicide


EDIT: this is about absolute position

Very old function findPos

http://www.quirksmode.org/js/findpos.html

Variante considering scroll & borders

function getPosition(el){
 var x=0,y= 0;
 while(el) {
  x+=(el.offsetLeft-el.scrollLeft+el.clientLeft);
  y+=(el.offsetTop-el.scrollTop+el.clientTop);
  el=el.offsetParent;
 }
 return{x:x,y:y}
}

to get right

  var info=getPosition(element);
  console.log('marginRight: '+info.x-element.offsetWidth);

Note1: these are vanilla javascript functions that are compatible with older browsers. thats why jQuery is not needed.obiovsly the performance is much better than using jQuery.

Note2: there are many other versions if you search find position

getBoundingClientRect

to get the right

  var info=element.getBoundingClientRect(); // Native Javascript ..think 1.6+
  console.log('marginRight: 'info.right-info.width);

Conclusion

There is no easy way to get the dimensions,offsets,applied css of an element if you want a allround compatible script.

the getPosition function is probably the best function (considering compatibility) that allows you to easely calculate this values..

Note: as there is a while loop inside the function, on very old machines you could get some problems with heavely nested elements.

if your using html5 and css than go for getBoundingClientRect

Note: probably both break when using css3 transforms.

EDIT

I need values that are equivalent to the .css('right') values that Firefox returns

To get those values you first need to find the position of the element.

So:getPosition function or getBoundingClientRect

then you need to calculate the top/bottom,left/right values.

left=x
right=x-width
top=y
bottom=y-height

EDIT2:

To apply this only to the parent element you need to execute getPosition also on the parent element

and the calculations are shown in @kalley's answer.

like image 30
cocco Avatar answered Sep 22 '22 16:09

cocco