杀了个回马枪,还是说说position:sticky吧

这篇文章发布于 2018年12月2日,星期日,18:04,归类于 CSS相关。 阅读 180061 次, 今日 101 次 105 条评论

 

一、Chrome杀了个回马枪

position:sticky早有耳闻也有所了解,后来,Chrome放弃了对其支持,我也就不关心这个声明了,今天偶然发现,卧槽,Chrome什么时候杀了个回马枪,居然又支持了。眼瞅着,各个浏览器纷纷立了山头,要必要关心关心position:sticky了,不要被人留下厚此薄彼的口舌。

position:sticky兼容性

Safari目前还需要-webkit-私有前缀。

二、position:sticky简介

单词sticky的中文意思是“粘性的”,position:sticky表现也符合这个粘性的表现。基本上,可以看出是position:relativeposition:fixed的结合体——当元素在屏幕内,表现为relative,就要滚出显示器屏幕的时候,表现为fixed。例如,可以滚动下面这个框框感受下交互表现:

其中导航元素设置了如下CSS:

nav {
    position: -webkit-sticky;
    position: sticky;
    top: 0;
}

于是,正如大家看到,随着页面的滚动,当导航距离上边缘0距离的时候,黏在了上边缘,表现如同position:fixed

//zxx: position:sticky要想生效,top属性或则left属性(看滚动方向)是必须要有明确的计算值的,否则fixed的表现不会出现。

这就是position:sticky最基本的表现,特别适合导航的跟随定位效果。

转折示意图片

很多人以为position:sticky就上面这点效果,就好像以为就是个平常的史莱姆一样,实际上,position:sticky可以实现性价比极高,甚至还有点小酷的交互布局效果。嘿嘿,这可是皇帝的夜壶——不是人人都能看到的哟。

三、富有层次的滚动交互

滚动下面这个嵌入页面的滚动条,我们可以看到新闻标题依次推上去,网友评论也会在恰当的时间从背后钻出来。

如果上面页面显示不出来,可以狠狠地点击这里:position:sticky实现的富有层次的滚动交互demo

GIF录屏效果如下:

GIF录屏效果截图

四、你可能不知道的position:sticky

position:sticky有个非常重要的特性,那就是sticky元素效果完全受制于父级元素们

这和position:fixed定位有着根本性的不同,fixed元素直抵页面根元素,其他父元素对其left/top定位无法限制。

根据我简单的测试,发现了sticky元素以下一些特性表现:

  1. 父级元素不能有任何overflow:visible以外的overflow设置,否则没有粘滞效果。因为改变了滚动容器(即使没有出现滚动条)。因此,如果你的position:sticky无效,看看是不是某一个祖先元素设置了overflow:hidden,移除之即可。
  2. 2019-05-22新增
    父级元素设置和粘性定位元素等高的固定的height高度值,或者高度计算值和粘性定位元素高度一样,也没有粘滞效果。我专门写了篇文章深入讲解了粘性效果无效的原因,可以点击这里查看
  3. 同一个父容器中的sticky元素,如果定位值相等,则会重叠;如果属于不同父元素,且这些父元素正好紧密相连,则会鸠占鹊巢,挤开原来的元素,形成依次占位的效果。至于原因需要理解粘性定位的计算规则,同样点击这里查看
  4. sticky定位,不仅可以设置top,基于滚动容器上边缘定位;还可以设置bottom,也就是相对底部粘滞。如果是水平滚动,也可以设置leftright值。

下面,我们再看看看富有层次的滚动效果的实现原理。

五、层次滚动实现原理

首先,HTML结构如下(结构很重要):

<article>
    <section>
        <h4>网曝王宝强殴打马蓉</h4>
        <content>
            <p>12月2日,有网友爆料称...</p>
        </content>
        <footer>网友评论:...</footer>
    </section>
    <section>
        <h4>知情人爆料称马蓉闯入王宝强家拿剪刀对峙</h4>
        <content>
            <p>...</p>
        </content>
        <footer>网友评论:...</footer>
    </section>
    ...
</article>

其中,标题<h4>和底部<footer>设置了sticky定位,如下:

article h4, 
h4 {
    position: sticky;
    top: 0;
    z-index: 1;
}
content {
    position: relative;
}
footer {
    position: sticky;
    bottom: 50vh;
    z-index: -1;
}

由于每一段短新闻都在section标签中,属于不同的父元素,因此,滚动的时候,后面的新闻标题才能把前面已经sticky定位的新闻标题推开,这是sticky定位天然的特性,无需任何JavaScript的帮助。

如果,我们这里的HTML结构做调整,标题都是平级的,如下:

<article>
    <section>
        <h4>网曝王宝强殴打马蓉</h4>
        <content>
            <p>12月2日,有网友爆料称...</p>
        </content>
        <footer>网友评论:...</footer>
        <!-- 下一个短新闻 -->
        <h4>知情人爆料称马蓉闯入王宝强家拿剪刀对峙</h4>
        <content>
            <p>...</p>
        </content>
        <footer>网友评论:...</footer>
    </section>
    ...
</article>

则最终效果是所有sticky定位的新闻标题都会重叠在一起,这并不是我们想要的效果。所以,记住了,position:sticky布局的时候,使用合适的HTML结构很重要。


效果中,网友评论从后面钻出来的效果又是如何实现的呢?

两个关键点:

  1. 定位用的bottom,效果和top正好是对立的。设置top粘滞的元素随着往下滚动,是先滚动后固定;而设置bottom粘滞的元素则是先固定,后滚动;
  2. z-index:-1让网友评论footer元素藏在了content的后面,于是才有了“犹抱琵琶半遮面”的效果。

position:sticky polyfill

CSS `position: sticky`声明的Polyfill地址:https://github.com/wilddeer/stickyfill

可以兼容到IE9及其以上浏览器。

六、男人这辈子最重要的是什么?

这男人这辈子,最重要的一件事情,不是高考胜败,或者某场比赛输赢,最重要的绝对是找一个靠谱的老婆!

好的老婆可以让你不断进步,不断成长,一往无前,蒸蒸日上。正所谓一个成功男人的背后总有一个默默支持他的女人!而一个糟糕的老婆,……看看王宝强,我就不多说什么了。

所以,在座的诸位年轻才俊们,作为过来人,一定要给你们一些建议:找老婆,外表绝对不是最重要的,内心的品质绝对是最最重要的。那种性格暴烈,或者自卑压抑,或者好逸恶劳,或者总是损你贬你的女人,一定要敬而远之,至少千万不要迈进婚姻的殿堂。

这就像一个蝴蝶效应,你们要相处40年甚至更久,平时看似微不足道对你的不好的影响,那日积月累就会质变;反之,如果是贤妻,久而久之,你就会慢慢超越那些家门不幸的男人,成为所谓成功的男人。

这远比你一场成功的面试,或者中一次锦鲤重要太多太多了。

皮囊不重要,关键内在,内在!

谨记!

(本篇完)

分享到:


发表评论(目前105 条评论)

  1. 代码如诗如画说道:

    末尾的急转弯,厉害了 666

  2. snowPeak说道:

    本文中心思想,标题6

  3. CommandNotFound ⚡️ 坑否说道:

    最后文章 亮了!

  4. overflow说道:

    top:0
    bottom:20px

    感觉是
    top 最小:10px
    bottom 最小: 20px
    因为他们能滚出屏幕的

  5. deep说道:

    最后一段让整篇文章都有了升华啊,从技术到人生* o *

  6. mfk说道:

    最后那段,应该是他老婆逼他写的

  7. 奋斗2号说道:

    没有很明显的感受到“犹抱琵琶半遮面”的效果。 * o *

  8. 奋斗2号说道:

    ~ o ~ 做一个好老婆!

  9. 青火说道:

    最后一波措不及防的PUA

  10. 卖剑买酒醉勾栏说道:

    满满的干货,尤其是最后一部分。(手动滑稽)(建议评论区加上表情功能啊~)

  11. 妙音天女说道:

    最终更正:
    1. 父级元素不能有任何overflow:visible以外的overflow设置,否则没有粘滞效果。因为改变了滚动容器(即使没有出现滚动条)。因此,如果你的position:sticky无效,看看是不是某一个祖先元素设置了overflow:hidden,移除之即可。
    2. 父级元素也不能设置固定的height高度值,否则也没有粘滞效果。
    3. 同一个父容器中的sticky元素,如果定位值相等,则会重叠;如果属于不同父元素,则会鸠占鹊巢,挤开原来的元素,形成依次占位的效果。

    改为

    1. 不能有任何祖先元素设置overflow:hidden,否则没有粘滞效果。因为改变了滚动容器(即使没有出现滚动条)
    2. 当sticky元素的父元素已不再完整占据sticky元素的固定区域时,sticky元素不再固定
    因此,
    ① 父级元素的height必须超过sticky元素的height,这样在height范围内有粘滞效果。
    ② 同一个父容器中的sticky元素,如果定位值相等,则会重叠;如果属于不同父元素,则会随着父元素不再完整占据sticky元素的固定区域以后,再由其他父元素的sticky子元素占据固定位置

  12. 妙音天女说道:

    1. 父级元素不能有任何overflow:visible以外的overflow设置
    应该改为
    父级元素不能有任何overflow:hidden的设置
    2. 同一个父容器中的sticky元素,如果定位值相等,则会重叠;如果属于不同父元素,则会鸠占鹊巢,挤开原来的元素,形成依次占位的效果。
    应该改为
    同一个父容器中的sticky元素,如果定位值相等,则会重叠;如果属于不同父元素,则会随着父元素1滚出viewport开始,父元素2下的sticky元素鸠占鹊巢,挤开原来的父元素1下的sticky元素,形成依次占位的效果。

  13. 陈 jm说道:

    sticky元素好像也没有BFC特性呢。。。
    至少我的浏览器是这样子,谷歌77

  14. 卷家老大说道:

    老婆自卑压抑怎么办。。。。。

  15. 小欢说道:

    文中第四大点指出“父级元素不能有任何overflow:visible以外的overflow设置,否则没有粘滞效果”,但是我设置。但是我设置父元素的overflow为auto后,position:sticky还能生效。有点疑惑…求解答
    代码地址:https://codepen.io/chenweihuan/pen/PooZQZa

  16. 霜燃说道:

    position:sticky我试过了,要想成功就得做到第六点。

  17. 眼睛眯起来说道:

    所以可以选择单身,没事保健一下子,得劲

  18. Tusi说道:

    厉害呀

  19. xman说道:

    看在第六点的份上,这篇文章我保存了。

  20. crazyjialin说道:

    记下来,旭哥!

  21. YugiAsuna说道:

    大佬您好,我自己写了好几个demo,发现在父元素上设置固定高度实际上也是能产生效果的,并且不管是固定值还是百分比都能生效。还有父级元素设置overflow时,除了hidden,默认的visible、auto、scroll、甚至fragments也都是能生效的。然后还发现设置了position:sticky的元素他是相对直接父元素的,就是说这个元素随页面滚动时只要碰到了直接父元素的地步,就会直接随页面滚上去了,绝对不会滚出直接父元素的范围这样,其他的还有待测试。

    • codercoca说道:

      发现在父元素上设置固定高度实际上也是能产生效果的,如下面https://codepen.io/xgheaven/pen/zMjPRL/

  22. hello,nihao说道:

    我怎么没成功

  23. helloworld说道:

    第六点才是关键

  24. 段增辉说道:

    感谢大佬分享

  25. 周沒有说道:

    博主可以看下这篇文章吗?
    https://developers.google.com/web/updates/2017/09/sticky-headers
    用position: sticky的时候一般来说需要根据它的位置进行相应的动画,然而并没有原生的api支持,这篇文章中用到了IntersectionObserver来监听,无奈我才疏学浅,根本无法理解其中各个函数的含义.
    大神有空可以看一看,把心得分享一下啊,感谢!

  26. 村里刚通电就赶紧敲几行代码说道:

    我试了一下,把html和body都设置成height:100%,最外层的div设置成height:100%,overflow-y:auto,这个div里有若干元素,把中间的一个nav元素设置成position:sticky;top:0;
    这样在父元素上设置了高度,发现没有影响position:sticky的正常表现,仍然可以达到想要的效果

  27. Mask2012说道:

    从sticky讲到找老婆,博主博学多才,博学多才!

  28. Handpear说道:

    试了下父级元素设置height:100%;都会没效果…

    • 村里刚通电就赶紧敲几行代码说道:

      我设置height:100%,发现效果正常,在华为荣耀v9和iphone6 ios10+上几个主流浏览器上都测试了

  29. gentlecoder说道:

    原来还可以这样用~赞👍~张老师文章最后一段都是精华呀

  30. redbuck说道:

    我脚的最后一段是嫂夫人拿刀架脖子写的

  31. ljybill说道:

    提交个错别字吧,第一章 要必要 -> 有必要 xD

  32. 小小笔记说道:

    这个sticky目前用于手机浏览器的兼容性整体如何呢~

  33. taia说道:

    居然说皮囊不重要,等着跪键盘吧

  34. athena说道:

    如果想在sticky生效的时候,加一些别的样式,现在是不是还是无法判断,什么时候这个元素会变成sticky呢,一般标题悬浮后会在下方加一些阴影,如果只是这一个属性,适用范围还是太少了

  35. lc说道:

    我给父元素设置overflow: scroll;子元素的sticky的属性没影响,所以您总结的sticky元素特性表现的第一点不够严谨

  36. lttplus说道:

    我这样写就是最后一个评论不会显示出来(我改了最后一个footer:bottom:0;就可以了)

  37. zky说道:

    尝试了下,h3{position: sticky; top: 30px;},当元素在屏幕内,也就是距离顶部距离大于30px时,会表现为position: static,此时top: 30px是无效的。为什么说是position:relative和position:fixed的结合体呢?

    • 张 鑫旭说道:

      说得好有道理~

    • lc说道:

      也就是距离顶部距离大于30px时,会表现position: relative;会相对于自己正常文档流的位置定位,可以通过设置top值的变化感受一下元素位置的变化,如果是static元素设置top,元素位置不会移动的

      • 陈 jm说道:

        我试了一下,在正常文档流中,sticky元素不会基于父元素定位。。。
        感觉是static和fixed的结合。

  38. iamobj说道:

    好文,原来还可以这么用,这个真是长知识了

  39. ddany说道:

    这样的老婆旺夫啊

  40. 说道:

    知道了,老婆要找性格好的才是本文重点

  41. 郭永顺说道:

    找老婆和sticky有什么关系,这弯转的有点陡。。

  42. 小小黑~说道:

    那女的勒~ 哈哈哈

  43. 章鱼猫说道:

    我的评论删除了吗

  44. 山佳说道:

    评论可以删除么

  45. saber酱说道:

    做导航很好啊,百度贴吧帖子里的导航就不自然,页面滚出屏幕后它 pia 的一下跑到顶部……导致内容部分都抖动了,很不舒服

  46. 心满说道:

    好像很有道理的样子 🍺

  47. 前端abc说道:

    大神,牛逼,膜拜!!!

  48. 游客4说道:

    哎,我女友脾气也是不好

  49. 好多水果说道:

    好的品质不是那么好找的啊啊!

  50. deiphi说道:

    记住了第六点,很有道理:)