让Sticky Header自动隐藏是一个一箭双雕的好办法,一来可以在任何页面任何地方都可以访问到导航条,二来可以节省页面空间。我的客户Easy Shine就非常乐意在自己的网站上使用这个技术,这个技术同时也在我的网站上实现了(viewport小于768px时可以看到效果)。
1 2 3 |
<header class="header" role="banner"> <!-- ... --> </header> |
1 2 3 4 5 6 7 8 9 |
.header { width: 100%; height: 7.5em; position: fixed; z-index: 1000; top: 0; left: 0; } |
这里有一些浅显易懂的HTML/CSS代码,无论页面滚动到何处,导航条都会固定在页面顶部。现在,我们如何让它自动隐藏?
自动隐藏导航条
「自动隐藏」意味着当用户在往下滚动页面时导航条将会消失,但当用户有可能需要导航条的时候又能让它出现:用户已经滚动到页面底部,或者开始向上滚动时。导航条的隐藏至少有两种形式:交互式和简单式。
交互式
交互式的意思是,导航条会直接地,或者立刻响应页面滚动事件,这种形式或许会由于它操作起来的感觉,从用户体验看来是一个良好的小细节。不过它也有不好的一面:这种形式的本质决定了他必须要依赖于JavaScript,我们不能使用JS事件节流阀(在指定的时间周期内只调用某个函数一次)。基本上这就意味着每次滚动事件产生都要产生计算,并且会毫无意义的占用CPU。幸运的是,大多数情况下这只是理论,实际上因为计算量实在太微不足道而通常不会遇到这种问题。
滚动事件产生时,JS算法会计算并修改CSS中的top
属性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//... window.addEventListener( 'scroll', function() { //... if( wScrollCurrent <= 0 ) // 滚动到页面顶部; 元素保持在页面顶部 element.style.top = '0px'; else if( wScrollDiff > 0 ) // 向上滚动事件; 元素插入页面 element.style.top = ( elTop > 0 ? 0 : elTop ) + 'px'; else if( wScrollDiff < 0 ) // 向下滚动事件 { if( wScrollCurrent + wHeight >= dHeight - elHeight ) // 滚动到页面底部; 元素插入页面 element.style.top = ( ( elTop = wScrollCurrent + wHeight - dHeight ) < 0 ? elTop : 0 ) + 'px'; else // 向下滚动事件; 元素消失 element.style.top = ( Math.abs( elTop ) > elHeight ? -elHeight : elTop ) + 'px'; } //... }); //... |
简单式
这种形式,取决于JavaScript节流阀的周期设置,或许不会有太多“得到回应”的感觉。不管怎么说,这种形式对CPU会比较友好,加之动画是基于CSS来实现的,这意味着我们的想象力可以尽情发挥。
和之前交互式不同的是,这里的JavaScript并不直接改变CSS的属性,而是为元素插入或移除header--hidden
这个CSS类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
//... window.addEventListener( 'scroll', throttle( throttleTimeout, function() { //... if( wScrollCurrent <= 0 ) // 滚动到页面顶部; 元素保持在页面顶部 removeElementClass( element, elClassHidden ); else if( wScrollDiff > 0 && hasElementClass( element, elClassHidden ) ) // 向上滚动事件; 元素插入页面 removeElementClass( element, elClassHidden ); else if( wScrollDiff < 0 ) // 向下滚动事件 { if( wScrollCurrent + wHeight >= dHeight && hasElementClass( element, elClassHidden ) ) // 滚动到页面底部; 元素插入页面 removeElementClass( element, elClassHidden ); else // 向下滚动事件; 元素消失 addElementClass( element, elClassHidden ); } //... })); //... |
在CSS中我们这样定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
.header { -webkit-transition-duration: .5s; transition-duration: .5s; -webkit-transition-timing-function: cubic-bezier( 0.215, 0.610, 0.355, 1.000 ); transition-timing-function: cubic-bezier( 0.215, 0.610, 0.355, 1.000 ); -webkit-transition-property: -webkit-transform; transition-property: transform; } .header--hidden { -webkit-transform: translateY( -100% ); -ms-transform: translateY( -100% ); transform: translateY( -100% ); } |
导航条的额外的一些状态
有些时候,尤其在主页中时,在页面顶部使用更大的导航条有助于获取访问者的注意,我们需要一个额外的CSS类来控制导航条高度:
1 2 3 4 |
.header--narrow { height: 5em; } |
然而这个新定义的CSS类是由JavaScript来控制如何使用的——在页面开始滚动时添加,并在滚动到页面顶部时移除。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// ... window.addEventListener( 'scroll', throttle( throttleTimeout, function() { // ... if( wScrollCurrent > elNarrowOffset ) // toggles "narrow" classname { if( !hasElementClass( element, elClassNarrow ) ) addElementClass( element, elClassNarrow ); } else removeElementClass( element, elClassNarrow ); // ... })); // ... |
示范
这个Demo的源代码中包括了纯JavaScript(兼容IE9+)和依赖于jQuery的两种实现方式,尽管去研究去使用吧!