var offset = $(selector).offset();
The values of offset variable changes if we scroll the page up and down, i want the exact and fixed offset value
I had a very similar issue to the original question. The offset is kinda tricky. Hopefully, this will help solve your problems as it did mine. I have 3 JSFiddles to demonstrate.
offset().top
of your div element from the window, you will always get a static number (i.e. if the $(window)
is the thing that scrolls and you have a div inside the window with offset().top
applied, the div will always have a static number). This offset is the exact number of pixels the element exists from the top of the $(window)
no matter how far down you scroll. For each of my JSFiddles, I'll see how far down the object $('div#offset')
is from the top of it's scrolling container. In this first example, notice how the number doesn't change: https://jsfiddle.net/BrianIsSecond/ehkgh2gu/
$(window)
isn't the container that scrolls. You instead create a div that has an "overflow-y:scroll;" attribute set. In this case, the $('div#offset').offset().top
acts very differently than the previous example. You'll notice it changes as you scroll. For my JSFiddle example, I simply wrapped everything in div#overflow
that has overflow-y:scroll;
attribute set. See example:https://jsfiddle.net/BrianIsSecond/tcs390h6/ <--- Note too that div#overflow isn't 100% tall. I made it 100px short of 100%. I am using that to illustrate an easy mistake, which I will address next.
$('#overflow').scrollTop()
and add it to $('#offset').offset().top
(i.e. var ep = $('#offset').offset().top + $('#overflow').scrollTop()
). Basically, by adding these two changing numbers together, they 'sorta' cancel each other out, giving you the exact position of the div#offset
element... or do they? Well, this is where the position of the div#overflow
is important! You must, must, must take into account the position of the scrollable container. To do this, take $('#overflow').offset().top
and subtract it from $('#offset').offset().top
before you add $('#overflow').scrollTop()
. This will then factor in the position of the scrollable container from the window. See example:https://jsfiddle.net/BrianIsSecond/yzc5ycyg/
Ultimately, what you are looking for is something like this:
var w = $('#overflow'), // overflow-y:scroll;
e = $('#offset'); // element
$('#overflow').scroll(function(){
var wh = w.height(), // window height
sp = w.scrollTop(), // scroll position
ep = (e.offset().top - w.offset().top) + sp; // element position
console.log(ep);
});
UPDATE (10/11/17): I've created a function to help solve this problem. Enjoy!
/*
function: betterOffset
hint: Allows you to calculate dynamic and static offset whether they are in a div container with overscroll or not.
name: type: option: notes:
@param s (static) boolean required default: true | set false for dynamic
@param e (element) string or object required
@param v (viewer) string or object optional If you leave this out, it will use $(window) by default. What I am calling the 'viewer' is the thing that scrolls (i.e. The element with "overflow-y:scroll;" style.).
@return numeric
*/
function betterOffset(s, e, v) {
// Set Defaults
s = (typeof s == 'boolean') ? s : true;
e = (typeof e == 'object') ? e : $(e);
if (v != undefined) {v = (typeof v == 'object') ? v : $(v);} else {v = null;}
// Set Variables
var w = $(window), // window object
wp = w.scrollTop(), // window position
eo = e.offset().top; // element offset
if (v) {
var vo = v.offset().top, // viewer offset
vp = v.scrollTop(); // viewer position
}
// Calculate
if (s) {
return (v) ? (eo - vo) + vp : eo;
} else {
return (v) ? eo - vo : eo - wp;
}
}