最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - jquery offset top wrong value, but gets right on page resize - Stack Overflow

programmeradmin1浏览0评论

I want to achieve a sticky menu like the left navigation on this page: .3.2/scaffolding.html.

My menu is a nav element with position:relative (I tried static as well) that goes fixed when it reaches the top of the viewport.

here's my function:

$(document).ready(function() {
    function stickyNav() {
        var elementPosition = $('nav').offset();
        console.log(elementPosition);

        $(window).scroll(function(){
            if($(window).scrollTop() > elementPosition.top){
                $('nav').addClass("sticky");
            } else {
                $('nav').removeClass("sticky");
            }
        });
    }
    stickyNav();
}); //document ready

the console.log(elementPosition); returns an offset top of around 1200px on page load, which is wrong. But if i resize the page, the value changes to around 650px which is the correct offset top and the function does what it is supposed to be doing.

I've looked around and found out that offsetp top maybe wrong when it's on hidden elements, or it has issues with margins but I actually don't have any plex structure here, just a single visible nav element .

any help on figuring this out would be much appreciated! thanks!!

I want to achieve a sticky menu like the left navigation on this page: http://getbootstrap./2.3.2/scaffolding.html.

My menu is a nav element with position:relative (I tried static as well) that goes fixed when it reaches the top of the viewport.

here's my function:

$(document).ready(function() {
    function stickyNav() {
        var elementPosition = $('nav').offset();
        console.log(elementPosition);

        $(window).scroll(function(){
            if($(window).scrollTop() > elementPosition.top){
                $('nav').addClass("sticky");
            } else {
                $('nav').removeClass("sticky");
            }
        });
    }
    stickyNav();
}); //document ready

the console.log(elementPosition); returns an offset top of around 1200px on page load, which is wrong. But if i resize the page, the value changes to around 650px which is the correct offset top and the function does what it is supposed to be doing.

I've looked around and found out that offsetp top maybe wrong when it's on hidden elements, or it has issues with margins but I actually don't have any plex structure here, just a single visible nav element .

any help on figuring this out would be much appreciated! thanks!!

Share Improve this question edited Jul 3, 2016 at 18:46 valerio0999 asked Jul 3, 2016 at 18:26 valerio0999valerio0999 12.2k7 gold badges32 silver badges57 bronze badges 3
  • Where is stickyNav() called in your code as I don't see an invocation of it? Can you share the html for the nav tag that produces this issue? – Dennis Shtatnov Commented Jul 3, 2016 at 18:42
  • @DennisShtatnov updated, thanks – valerio0999 Commented Jul 3, 2016 at 18:46
  • Here is a minimally functioning example of your code working: jsfiddle/b4m3swhp/1. I'd suspect it is something to do with the structure of where <nav> is being placed or when it was inserted. If a resize is fixing it then it may be possible that some of your css is responsive and effecting the <nav> tag when the screen is a particular width. – Dennis Shtatnov Commented Jul 3, 2016 at 19:08
Add a ment  | 

2 Answers 2

Reset to default 3

jQuery(document).ready handler occurs when the DOM is ready. Not when the page is fully rendered.

https://api.jquery./ready/

When using scripts that rely on the value of CSS style properties, it's important to reference external stylesheets or embed style elements before referencing the scripts.

In cases where code relies on loaded assets (for example, if the dimensions of an image are required), the code should be placed in a handler for the load event instead.

So if you're using stylesheets that are loaded AFTER the script in question, or the layout of the page depends on image sizes, or other content, the ready event will be hit when the page is not in its final rendering state.

You can fix that by:

  1. Making sure you include all stylesheets before the script
  2. Making sure the CSS is more robust, and doesn't depend that much on content size (such as images)
  3. Or, you can do this on window load event.

Edit:

If you want to make your script dependent on more than one async event (like the loadCSS library), use this:

var docReady = jQuery.Deferred();
var stylesheet = loadCSS( "path/to/mystylesheet.css" );
var cssReady = jQuery.Deferred();
onloadCSS( stylesheet, function() {
    cssReady.resolve();
});
jQuery(document).ready(function($) {
    docReady.resolve($);
});
jQuery.when(docReady, cssReady).then(function($) {
    //define stickyNav

    stickyNav();
});

You can add a check to see if your CSS has loaded by setting a style tag in your document which shows a test element, and then overwrite this in your CSS file to hide it. Then you can check the status of your page by checking this element. For example...

In your HTML:

<div id="loaded-check" style="display:block; height:10px; width:10px; position:fixed;"></div>

In your CSS:

#loaded-check { display:none; }

In your jQuery script:

var startUp = function() {
    var cssLoaded = $('#loaded-check').is(':visible');
    if (cssLoaded) {
        $('#loaded-check').remove();
        doOtherStuff()
    }
    else {
        setTimeout(function() {
            startUp();
        }, 10);
    }
}

var doOtherStuff = function () {
    //bind your sticky menu and any other functions reliant on DOM load here
}
发布评论

评论列表(0)

  1. 暂无评论