创建一个固定导航栏的CSS和jQuery

3
我正在为一个网站设计一个固定导航栏,但遇到了一些问题。当导航栏变成position:fixed时,它似乎会跳动并且看起来很“笨重”。这是我尝试实现的代码示例:http://jsfiddle.net/DKtLR/。理想情况下,用户滚动页面时,导航栏不应该固定在一个位置,直到滚动出视口后才固定,并重新滑入视图中。

2
这个例子中,这将如何工作?菜单已经在页面顶部,没有任何情况下用户的视口会在菜单之上。如果菜单不在页面顶部,这可能会更好地起作用。 - Rodik
我还想说:如果它已经在页面顶部,请将其保留并立即修复。如果不是,则滚动它直到触及顶部,然后再进行修复。 - insertusernamehere
这就是我正在尝试做的事情,但感觉在固定时有一种跳跃的感觉。 - Udders
1
你应该看一下这个 - morgi
4个回答

2

如果你希望它只在完全移出视口后固定,然后滑入,请修改 top 属性并将其动画化回到视图中。请参见这个示例以获取可工作的示例。

更新

此更新示例应该更好地适用,因为它仅在未应用行为时才适用,并在返回正常的 '静态' 位置时完全删除动态样式。

请注意,在向上滚动时仍会闪烁 - 这是因为导航从其固定位置跳回其静态位置。可以使用类似上面动画的技术轻松解决此问题。


1
有没有办法在我向下滚动页面时停止导航闪烁?感谢你的示例,真是太棒了! - Udders
我在 Chrome 中没有看到任何闪烁,你用的是什么浏览器? - chrisfrancis27
在我的本地站点版本上实现时,Mac上的Chrome会闪烁。当页面很长且滚动时间较长时,肯定会出现闪烁问题。http://jsfiddle.net/D8V7b/2/ - Udders
这是一个类似于我的解决方案,尽管它并不真正基于菜单高度切换显示,而是基于一些预定义的尺寸。 - Robert Koritnik
是的,为了简洁起见,我使用了现有的尺寸,但当然你可以非常容易地检测到标题高度并使用它来代替。 - chrisfrancis27
@sico87,这个对你有用吗?很想看看你最终使用了什么。 - chrisfrancis27

1

0

在顶部并通过动画固定,以避免笨重

这可能是你正在寻找的解决方案,因为它提供了一个固定的菜单栏,当滚动超出视图时,但当它从顶部切换到固定时,它会执行一个下滑动画,所以它不会感觉像你描述的那样笨重

我在示例中使用的HTML(简化):

<div id="menu">
    <ul>
        <li><a href="#">Home</a></li>
        <li><a href="#">About</a></li>
        ...
    </ul>
</div>
<div id="content" />

CSS当然很简单(只涉及相关样式)

#menu {
    position: absolute;
    width: 100%;
}
#menu.out {
    position: fixed;
}
#menu ul {
    margin: 0;
    list-style: none;
}
#menu ul li {
    display: inline-block;
}

而且这个脚本可以快速地完成它的任务(因此它尽可能地快,因为最慢的部分是调用浏览器原生的getBoundingClientRect()函数,这意味着它仍然非常快):

$(function() {

    // save element references for faster execution
    var menu = $("#menu");
    var ul = menu.find("ul");
    var content = $("#content")[0];

    // get menu actual height
    var menuHeight = menu[0].getBoundingClientRect().bottom;

    // detect whether menu is scrolled out
    var inView= true;

    $(document).scroll(function(evt) {
        evt.preventDefault();

        var top = content.getBoundingClientRect().top;
        var nextInView = (top + menuHeight) > 0;

        // did state change so we have to change menu positioning
        if (inView ^ nextInView)
        {
            inView = nextInView;
            if (inView)
            {
                menu.removeClass("out");
            }
            else
            {
                menu.addClass("out");
                ul.hide().slideDown("fast");
            }
        }
    });

});

就是这样。您还可以通过动画化顶部样式属性来微调从slideDown()slide in的动画,同时您知道在视口上方放置菜单之前要放多少像素。

当您滚动页面并且菜单超出视图时,它会将其切换为固定位置并向下滚动菜单,以便它不仅能够跳转到视图,而是平稳地回到视图中


0

我基于这个解决方案制作了这个替代方案。它基于setInterval函数(请参见控制台日志)。

var interval_id = false;
var curOffset, oldOffset;
var altmenu;
$(document).ready(function(){
    altmenu = $('.top-nav')[0].cloneNode(true);
    altmenu.style.position = 'absolute';
    altmenu.style.display = 'none';
    document.body.appendChild(altmenu);
    oldOffset = $(window).scrollTop();
    $(document).bind('scroll',function(){
        if (interval_id) {
            return;
        }
        //altmenu.style.display = 'none'; // optional
        interval_id = setInterval(function() {
            curOffset = $(window).scrollTop();
            if(curOffset == oldOffset) {
                console.log('scrolling stopped',curOffset);
                clearInterval(interval_id);
                interval_id = false;
                if (curOffset>120) {
                    altmenu.style.display = 'block';
                } else {
                    altmenu.style.display = 'none';
                }
                $(altmenu).css({
                    top: (curOffset-120)+'px'
                }).animate({
                    top: (curOffset)+'px'
                }, 500);
            }
            oldOffset = curOffset;
        }, 500); //setInterval
    });//scroll
});//ready

测试脚本jsfiddle 在这里。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接