神奇的position:sticky

sticky定义

position:sticky定义,
eg:CSS中position属性介绍(新增sticky)

设置了sticky的元素,在屏幕范围(viewport)时该元素的位置并不受到定位影响(设置是top、left等属性无效),当该元素的位置将要移出偏移范围时,定位又会变成fixed,根据设置的left、top等属性成固定位置的效果。

sticky特点

sticky属性有以下几个特点:

  1. 该元素并不脱离文档流,仍然保留元素原本在文档流中的位置。
  2. 当元素在容器中被滚动超过指定的偏移值时,元素在容器内固定在指定位置。亦即如果你设置了top: 50px,那么在sticky元素到达距离相对定位的元素顶部50px的位置时固定,不再向上移动。
  3. 元素固定的相对偏移是相对于离它最近的具有滚动框的祖先元素,如果祖先元素都不可以滚动,那么是相对于viewport来计算元素的偏移量。

sticky的demo

sticky展现效果

看了效果我就会很清楚的知道他的作用,在实际应用中,eg:导航栏随屏幕滚动定位顶部,侧边栏广告随滚动定位顶部等。

以导航栏随屏幕滚动定位顶部为实例:

方案一:双导航实现原理

  1. 一个导航(1)在商品的上方(初始化导航一显示),一个导航(2)定位在窗口的顶部(初始化导航二隐藏);
  2. 然后实现滚动监听事件:

    1. 当滚动到大于等于导航(1)的位置时,导航(2)显示(导航一此时依然显示,只是我们用导航二层级将导航一遮挡)————-此时我们看到窗口顶部的导航是:导航(2)
    2. 当滚动到小于导航(1)的位置时,导航(2)隐藏(导航一显示)————–此时我们看到商品顶部的导航是:导航(1)

    优点:

    1. 兼容性比较好;
    2. 不会出现抖动的效果;
    3. 不会导致回流。

    缺点:

    1. 代码量较多;
    2. 浏览器计算消耗大;
    3. 在切换的时候会出现闪动的效果。
CSS代码
.module-nav{
    color: #ffea00;
    width: 7rem;
    font-size: 0.28rem;
    height: 0.65rem;
    line-height: 0.6rem;
    display: table;
    table-layout: fixed;
    padding: 0 0.25rem;
    text-align: center;
    background: #fbbd09;
}
.module-nav.nav1{
    position: fixed;
    top: 0;
    left: 0;
    z-index: 10000;
    display:none;
}
.module-nav span{
    display: table-cell;
    background: url(./images/nav-bg.jpg) no-repeat right center/1.7rem 0.65rem;
}
.module-nav span.active{color: #fff;}
HTML代码
<nav class="module-nav">
    <span class="active">生态餐桌</span>
    <span>茗茶名酒</span>
    <span>美食物语</span>
    <span>居家生活</span>
</nav>
<nav class="module-nav nav1">
    <span class="active">生态餐桌</span>
    <span>茗茶名酒</span>
    <span>美食物语</span>
    <span>居家生活</span>
</nav>
JS代码
$(window).scroll(function(){
    var bodyTop = $('html,body').scrollTop();
    var goodTop = $('.goods').offset().top;
    bodyTop >= goodTop ? $('.nav1').show() : $('.nav1').hide();
});

注意:在移动端如果导航要居中显示,要对nav1的left进行计算赋值。

方案二:单导航

通过对导航的position的值在fixed和relative切换,来实现

优点:

  1. 比第一种方案少了一个导航,直接在一个导航操作

缺点:

  1. 依然需要JS来监听,进行position的值切换
  2. 切换时会导致回流
  3. 切换回导致每个楼层的offset().top值的改变,所以每次都需要重新获取
CSS代码
.module-nav{
    position: relative;
    top: 0;
    left: 0;
    z-index: 10000;
    color: #ffea00;
    width: 7rem;
    font-size: 0.28rem;
    height: 0.65rem;
    line-height: 0.6rem;
    display: table;
    table-layout: fixed;
    padding: 0 0.25rem;
    text-align: center;
    background: #fbbd09;
}
.module-nav span{
    display: table-cell;
    background: url(./images/nav-bg.jpg) no-repeat right center/1.7rem 0.65rem;
}
.module-nav span.active{color: #fff;}
HTML代码
<nav class="module-nav">
    <span class="active">生态餐桌</span>
    <span>茗茶名酒</span>
    <span>美食物语</span>
    <span>居家生活</span>
</nav>
JS代码
$(window).scroll(function(){
    var bodyTop = $('html,body').scrollTop();
    var goodTop = $('.goods').offset().top;
    bodyTop >= goodTop ? $('.module-nav').css('position','fixed') : $('.module-nav').css('position','');
});

注意:在fixed定位的时候需要进行left的计算,否则会导致导航的不居中。

方案三:sticky实现原理

直接对导航使用position:sticky,就能实现上边看着复杂的效果。

优点:

  1. 代码量少;
  2. 不用JS监听滚动事件,减少了浏览器计算的消耗;
  3. 不会触发 BFC。BFC详解

缺点:

  1. 兼容性不是很好;
  2. sticky 是容器相关的,也就说 sticky 的特性只会在他所处的容器里生效。看看这个demo你就明白了
CSS代码
.module-nav{
    position: sticky;
    top: 0;
    left: 0;
    z-index: 10000;
    color: #ffea00;
    width: 7rem;
    font-size: 0.28rem;
    height: 0.65rem;
    line-height: 0.6rem;
    display: table;
    table-layout: fixed;
    padding: 0 0.25rem;
    text-align: center;
    background: #fbbd09;
}
.module-nav span{
    display: table-cell;
    background: url(./images/nav-bg.jpg) no-repeat right center/1.7rem 0.65rem;
}
.module-nav span.active{color: #fff;}
HTML代码
<nav class="module-nav">
    <span class="active">生态餐桌</span>
    <span>茗茶名酒</span>
    <span>美食物语</span>
    <span>居家生活</span>
</nav>

注意:由于兼容性问题,所以sticky可以在移动端使用,代码简单,容易理解。但是要注意所选择的容器!

其他

我的博客,欢迎交流!

我的CSDN博客,欢迎交流!

微信小程序专栏

前端笔记专栏

微信小程序实现部分高德地图功能的DEMO下载

微信小程序实现MUI的部分效果的DEMO下载

微信小程序实现MUI的GIT项目地址

微信小程序实例列表

前端笔记列表

游戏列表

posted @ 2017-11-21 13:54  Newman·Li  阅读(785)  评论(0编辑  收藏  举报