jquery offset values changes by scrolling the page

前端 未结 6 1689
南旧
南旧 2020-12-15 16:55
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

6条回答
  •  北海茫月
    2020-12-15 17:39

    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.

    1. If you are basing the 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/

    1. Now, lets say that the $(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.

    1. If your like me, example 2 isn't what you were wanting. The best solution I have found is to grab $('#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;
            }
    }
    

提交回复
热议问题