【问题标题】:jquery offset top wrong value, but gets right on page resizejquery偏移顶部错误的值,但在页面调整大小时正确
【发布时间】:2016-07-03 18:26:42
【问题描述】:

我想在这个页面上实现一个像左侧导航一样的粘性菜单:http://getbootstrap.com/2.3.2/scaffolding.html

我的菜单是一个nav 元素,带有position:relative(我也试过static),当它到达视口顶部时,它会变为fixed

这是我的功能:

$(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

console.log(elementPosition); 在页面加载时返回大约 1200 像素的偏移顶部,这是错误的。但是,如果我调整页面大小,该值会更改为 650px 左右,这是正确的顶部偏移量,并且该函数会执行它应该做的事情。

我环顾四周,发现 offsetp top 在隐藏元素上可能是错误的,或者它有边距问题,但我实际上没有任何复杂的结构,只有一个可见的 nav 元素。

任何有关解决此问题的帮助将不胜感激!谢谢!!

【问题讨论】:

  • 您的代码中在哪里调用了stickyNav(),因为我没有看到它的调用?你能分享产生这个问题的 nav 标签的 html 吗?
  • @DennisShtatnov 已更新,谢谢
  • 这里是您的代码工作的最小功能示例:jsfiddle.net/b4m3swhp/1。我怀疑这与放置

标签: javascript jquery offset sticky window-resize


【解决方案1】:

jQuery(document).ready 处理程序在 DOM 准备好时发生。当页面完全呈现时不是。

https://api.jquery.com/ready/

当使用依赖 CSS 样式属性值的脚本时, 引用外部样式表或嵌入样式很重要 引用脚本之前的元素。

如果代码依赖于加载的资源(例如,如果 图像的尺寸是必需的),代码应放在 而是加载事件的处理程序。

因此,如果您使用在相关脚本之后加载的样式表,或者页面布局取决于图像大小或其他内容,则当页面未处于最终状态时,ready 事件将被触发渲染状态。

您可以通过以下方式解决此问题:

  1. 确保在脚本之前包含所有样式表
  2. 确保 CSS 更加健壮,并且不太依赖于内容大小(例如图片)
  3. 或者,您可以在窗口load 事件上执行此操作。

编辑:

如果您想让您的脚本依赖多个异步事件(例如loadCSS 库),请使用:

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();
});

【讨论】:

  • 这是一个很好的答案!事实上,我的 css 是异步加载的(github.com/filamentgroup/loadCSS),这可能是发生这种情况的原因吗?有没有办法在添加 css 后启动该功能?谢谢
  • 您可以为您拥有的每个异步加载创建一个Deferred jQuery 对象:文档准备好、css 加载等。每次加载后,只需解决承诺。所以把你的代码放在jQuery.when(promises).then(functionWhenAllIsOk, functionWhenNotAllOk) api.jquery.com/jQuery.when 你可以用你的loadCSS 使用这个:var stylesheet = loadCSS( "path/to/mystylesheet.css" ); onloadCSS( stylesheet, function() { console.log( "Stylesheet has loaded." ); });
【解决方案2】:

您可以通过在文档中设置一个显示测试元素的样式标签来检查您的 CSS 是否已加载,然后在您的 CSS 文件中覆盖它以隐藏它。然后,您可以通过检查此元素来检查页面的状态。比如……

在您的 HTML 中:

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

在您的 CSS 中:

#loaded-check { display:none; }

在您的 jQuery 脚本中:

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
}

【讨论】:

  • 这正是加载事件的用途。
  • 实际上 onload 事件是针对 DOM 加载完成的,与浏览器应用 css 样式无关。这两个事件之间通常存在滞后。我经常看到人们使用超时来尝试避免在页面加载时过早获取元素高度或偏移量。我的解决方案只是旨在成为一种比这更受控制的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多