What is the difference between getBoundingClientRect().top and offsetTop?
https://codepen.io/anon/pen/bWZWQg
const elem = document.querySelector('#find');
console.log('getBoundingClientRect: ' + elem.getBoundingClientRect().top);
console.log('offsetTop: ' + elem.offsetTop);
// Stuff to push the div down the page
<div id='find'>Find me</div>
From my quick test the only difference seems to be the number of decimal places returned.
getBoundingClientRect gives you offset relative to your client viewport, While offsetTop is always fixed static property. although it changes when the actual position of the element changes on document. For real clarification go to pen and you can check the difference your self.
If element is inside relative container then offsetTop will be relative to the given container
pen
console.log('offsetTop: ' + elem.offsetTop); //This is fixed. it get's calculated from beginning of your page to actual element's position.
console.log('getBoundingClientRect: ' + elem.getBoundingClientRect().top); // this will changing while scroll, because it's relative to your current view port.
see the pen, scroll the div and while doing that check the console.
In case container of the element is relative then
console.log('offsetTop: ' + elem.offsetTop) // //This is fixed. it get's calculated from beginning of your top most relative container.
The HTMLElement.offsetTop read-only property returns the distance of the current element relative to the top of the offsetParent node.
getBoundingClientRect() is a very useful, cross browser safe method that returns top, right, bottom, and left position of any element relative to the viewport.
The method getBoundingClientRect may not be as good in performance as offsetLeft (doc here), but if you wanna know an element's position after it transformed by CSS, or even still in transition animation, it is the best choice (maybe the only way).
Here is a Related answer.
Related
I am using jQuery offset().top to calculate a hyperlink's pixels from the top of the document window so that when hovered, a tooltip can appear above it.
By default, the tooltip's css has an absolute position of top 0 and left 0. When the link is hovered, it calculates it's position from the top of the document and uses that as the css top position for the tooltip.
The problem is that on some pages, offset is calculating the link's position perfectly, and on others, it is around 50 pixels too many. I can't figure out why.
$(".tiptrigger").mouseenter(function() {
var s_id = $(this).attr('id');
var calc = $(this).offset().top;
$("#tip-"+s_id).css({"margin-top": calc+"px"});
});
Instead of absolute try to use fixed for your popup element. Than offset().top should work if you don't have any unnecessary padding applied to body
If still inaccurate instead of .offset().top give a chance to https://developer.mozilla.org/en-US/docs/Web/API/element.getBoundingClientRect
.offset() has this limitation:
Note: jQuery does not support getting the offset coordinates of hidden elements or accounting for borders, margins, or padding set on the body element.
So your jQuery is probably correct but if you have some padding/margin on your body, you will experience an incorrect offset. Either remove it or include it in your calculation:
var bodyOffset = $('body').css("margin-top") + $('body').css('padding-top') + $('body').css('border-top');
var calc = $(this).offset().top + bodyOffset;
My question is fairly straightforward: How can you find the offsetTop of a child element compared to it's parent element (rather than the window top)?
The definition of offsetTop states that the property will return the value by which a child element is offset from the top of an offsetParent, but this doesn't seem to be the case in this JSFiddle: http://jsfiddle.net/h5KBK/.
My goal is to find the offset of the bolded orange text from the top of the scrollable div, not the window top. Is there any way to do this without calculating the heights of the above elements, paddings, margins, etc. and subtracting it from the offsetTop?
I'm looking for a JavaScript only solution. No jQuery please.
By definition offsetTop returns the top position of the object relative to the top side of its offsetParent element, in pixels.
Now offsetParent needs to be an element with a position other than static. If you change the position attribute of scroll element in your fiddle I get a value of 1012 as opposed to 1110 without the position attribute.
Actually, I did some more research and figured out the answer. The offsetParent must have a specified position:absolute or position:relative declaration, as shown in this JSFiddle: http://jsfiddle.net/h5KBK/1/
I have this element, and i want to position it to specific coordinates on the page. The problem is that it's inside another positioned element, so position:absolute places it relatively to this element, while i want it to be placed relatively to the page.
Is there some way i can place an element at specific coordinates on the page?
You can see what i have on this page: http://bit.ly/NkfJk7 when you mouse over that yellow exclamation icon, i want the pink box to appear near that, but instead it appears in double that distance.
I figured it out, i was doing it wrong.
toolTip.style.left = button.offsetLeft + "px";
toolTip.style.top = button.offsetTop + "px";
No need to go absolute :)
You can use position: fixed for this
https://developer.mozilla.org/en/CSS/position
Fixed
Do not leave space for the element. Instead, position it at a specified position relative to the screen's viewport and doesn't move when scrolled. When printing, position it at that fixed position on every page.
EDIT: Disregard this answer. Position-fixed positions relative to the screen, so it will follow around it the page scrolls.
This is a followup to my question here. I would like to understand why applying position:absolute to the CSS of a div via jQuery fails, while applying it in a static style works. Here are two jsfiddle examples:
Works: http://jsfiddle.net/jasper/Ty6Af/2/
No worky: http://jsfiddle.net/Ty6Af/3/
Note that the only difference between the two is where I apply position:absolute. Vertical centering always works, but horizontal centering does not work when the page loads for the first time. If you manually re-size the window the div will center correctly.
All of my testing has been on Chrome under Ubuntu thus far.
Anyway, I'm just now delving into the world of web development and these are exactly the kinds of 'quirks' that I need to begin understanding.
EDIT:
#Jasper found something interesting. If you make two calls to .css(), first applying position and subsequently applying a margin, it works. I would love to understand why. Here is an example: http://jsfiddle.net/jasper/Ty6Af/5/
So the issue is with how the width of the div is calculated by the browser depending on its position.
If the div is set to position : static (by default) then it's width is 100% of it's parents width and the element is not allowed to move around the page.
If the div is set to position : relative then it's width is 100% of it's parents width but it can be moved around with left.
If the div is set to position : absolute then its width is determined by the actual content of the div, for instance if there is only a 200px wide <span> element within the div then the div will be 200px wide.
You can test these observations by changing the CSS of your jsfiddle to specify position : relative (etc...) and remove the JavaScript that makes the div position : absolute, then use your Developer Tools to inspect the element and it's calculated width.
The problem with your code is that it sets the position : absolute at the same time it sets the margin of the element by using its width/height (which are calculated differently depending on the position of the element).
If you want to set the position of the div in JavaScript then you can do something like this:
$(function() {
//notice I cached the selector so it can be used in the future as well as set the position of the div
$signuparea = $('#signuparea').css({position : 'absolute'});
$(window).resize(function() {
$signuparea.css({
'margin-top' : '-' + Math.round($signuparea.height() / 2) + 'px',
'margin-left' : '-' + Math.round($signuparea.width() / 2) + 'px',
});
}).trigger('resize');
});
Here's a jsfiddle: http://jsfiddle.net/jasper/Ty6Af/8/
I believe the problem is that when you apply your left and right in your second fiddle, you have yet to add position absolute to the div. Hence, the browser has no idea what do with the left and right values and ignores them initially.
Practically speaking in your second fiddle, you only actually add the position:absolute on the resize trigger. So before you resize your actual div has no positioning.
If you instead add the position absolute on load it works fine:http://jsfiddle.net/Ty6Af/9/
Notice that if you give it position:relative from the start (like this http://jsfiddle.net/Ty6Af/11/ ) it allready applies both the left and right value. The reason you can't actually see the effect of "left" is because it is a block element.
I hope that answers your question, I'm not quite clear on where you are stuck.
http://jsfiddle.net/Ty6Af/7/ this should work, the trigger function in jquery has bugs with chrome so you have to run the function on load too.
The problem seems to be that position:absolute; negates the current layout and requires you to position it.....
See: http://jsfiddle.net/ZHaRD/
Which Jasper explains much more eloquently than myself!
How can I possibly change Javascript's origin? For example, if I were to call offsetTop on a div, it's really tell me how far it is from the origin. Javascript's origin is at the top left of the page, but how can I move that?
I want to make it at the bottom left.
Your information about offsetTop is incorrect. From MDC:
offsetTop returns the distance of the current element relative to the top of the offsetParent node.
You cannot "move" the origin in the way you are thinking, though you could use a bit of math to compute the distance from the element's top edge to the bottom of the screen/page. Using jQuery (for clarity, so the code isn't mucked up with cross-browser feature detection):
var $doc = $(document),
docHeight = $doc.height(),
$elt = $('#some-element-id'),
top = $elt.offset().top,
// this is the value you're interested in
originShiftedTop = docHeight - top;
Demo. Try re-running the fiddle with different Result pane heights.
Note that jQuery's .offset() returns the position of the element relative to the document, unlike element.offsetTop the DOM-standard property. jQuery's .position() function behaves like element.offsetTop.