jquery offset values changes by scrolling the page

前端 未结 6 1675
南旧
南旧 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:33

    One other potential cause is if your <body> happens to have CSS that sets overflow-x: hidden; - that completely breaks jQuery's offset() method.

    In that case, $(window).scrollTop() is always 0, so the accepted answer does not work.

    0 讨论(0)
  • 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;
            }
    }
    
    0 讨论(0)
  • 2020-12-15 17:49

    Just wanted to add my answer here after having the same issues:

    After getting the behaviour described above I looked at the jQuery documentation and discovered that

    jQuery does not support getting the offset coordinates of hidden elements or accounting for borders, margins, or padding set on the body element.

    The element I was trying to get the offset of was in fact set to display:none; giving me a false offset which changed when scrolling (even though the element didn't move).

    So make sure you're not trying to get an offset of a hidden element! hope this helps someone :)

    0 讨论(0)
  • 2020-12-15 17:49

    In 2015, the 'correct' answer should no longer be used - offset has been modified. Any code that used the above solution will no longer work properly.

    Solution: Please upgrade jquery to a newer version (works in 1.11.3). Or... change .offset call to use .position instead.

    0 讨论(0)
  • 2020-12-15 17:54

    I am having the same problem while editing a old website the workaround I find out is to use $(selector)[0].offsetTop instead of $(selector).offset().top and it is working fine for me right now.

    0 讨论(0)
  • 2020-12-15 18:00

    You could always calculate the offset, factoring in the scroll position:

    var offset_t = $(selector).offset().top - $(window).scrollTop();
    var offset_l = $(selector).offset().left - $(window).scrollLeft();
    
    0 讨论(0)
提交回复
热议问题