CSS Sticky 其实很简单
为什么要写这篇文章
Sticky
也不是新知识点了,写这篇文章的原因是由于最近在实现效果的过程中,发现我对 Sticky
的理解有偏差,代码执行结果不如预期。决定写篇文章重新学习一次。
什么是 Sticky
Sticky
(MDN 翻译成粘性效果)是 CSS
属性 position
中的一个可选值。跟我们用得比较多的 static
, fixed
,relative
,absolute
一样,用来描述元素的定位方式。
从效果上看,Sticky
像是混合体,页面滑动到“临界点”之前表现为 relative
, 到达“临界点”时表现为 fixed
。
如何使用
使用 CSS Sticky
只需要两个条件。
position: sticky;
top: 0; // right/bottom/left 任一有效值,甚至可以为负像素值
复制代码
top:0
意思是当元素滑动到距离视口 0px 时再继续滑动,元素吸顶。可以在 这里 看效果(试试看修改 top 值)
对比 JS 的实现方案
没有 CSS Sticky
之前,类似的效果都是使用 JS 实现。大致步骤如下:
- 监听滚动事件,计算目标元素距离视口的距离。
- 距离不满足条件时,按兵不动。
- 距离满足条件时,创建占位元素,修改目标元素定位方式为
fixed
。
window.addEventListener('scroll', () => {
const rect = elem.getBoundingClientRect();
// 计算目标元素和视口的距离
})
复制代码
在 npm 上搜 sticky 关键字,也有很多优秀的包可以使用。以 react-sticky 为例,满足条件时会创建 placeholder
元素(防止页面抖动),同时让 header
定位为 fixed
。
右边是 Chrome Dev-Tools
的 layers
面板,蓝色部分为生成的 placeholder
。
两种方案的火焰图对比(为了放大效果,我把 cpu
调慢了 6 倍)
CSS 方案
使用 CSS Sticky
,工作都交给 GPU
了,不占用 JS
主线程的资源,在移动端上异常流畅。
React Sticky
由于需要在 scroll event
回调中不断调用 getBoundingClientRect
,而 getBoundingClientRect
又会触发页面重排重绘,稍不留神就掉帧卡顿。仅仅为了实现这个效果(页面上没有其他内容)大动干戈性价比很低。
结论是:实现 Sticky
效果,优先选择 CSS Sticky
理解上的偏差
1. 只在 Containing Block 内有效。
修改例子,用一个 div 把 Sticky Header
包裹起来,发现 Sticky
效果失效了!!!
...
<div class="wrapper">
<header>Sticky Header</header>
</div>
...
复制代码
根据文档,Sticky
效果只在 Containing Block 内有效,Containing Block
滑出屏幕时,Stickey Element
也跟着滑走。
修改 wrapper
的高度,看效果。
.wrapper {
height: 100px;
background-color: #e6e6e6;
}
复制代码
多个 Sticky Element
放在一块就有了前一个被后一个顶出去的特效,实际上并不是真的被顶出去,而是 Containing Block
把它拖走。
2. Overflow 会影响 Sticky
修改例子中的代码,给 #root
加上 overflow: auto
#root {
overflow: auto;
}
复制代码
Sticky
效果再次丢失(overflow
设置为其他非 visible
的有效值也是同样效果。)
看了很多相关的文档,我的出来的结论是:
Sticky Element
的 offset 值是依据 nearest scrolling ancestor
(距离最近的滚动祖先) 计算的,如果没有匹配上的祖先元素,则使用视口作为参照物。
问题就出在 overflow-x
或者 overflow-y
其中任一为非 visible
则认为是要找的目标元素,而在滚动窗口的过程中,Sticky Element
和 它找到的目标祖先元素的 offset
值一直没有改变,所以 Sticky
不起作用。
对症下药,让滚动发生在被“误匹配”上的祖先元素内即可恢复 Sticky Effect
。
#root {
overflow: auto;
height: 100vh;
}
复制代码
兼容性
算上 prefixed
,当前 css sticky
手机端兼容性达到 94.14%,如果你所做的业务需要照顾剩下 5.86% 的用户,也可以使用 polyfill 或者 position: fixed
。
相关链接
作者:HelKyle
链接:https://juejin.im/post/5cde75636fb9a07ef562048a
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
CSS Sticky 其实很简单的更多相关文章
- 一个神奇却很简单的css特效
在网上看到一个前端大牛的主页,觉得他有一个特效特别酷,一开始还以为是要用什么javascript代码来实现,但仔细看一下,发觉只是用几行css代码就搞定了,我觉得挺好的. 他这个效果就是鼠标放在左半部 ...
- CSS Sticky Footer
----CSS Sticky Footer 当正文内容很少时,底部位于窗口最下面.当改变窗口高度时,不会出现重叠问题. ----另一个解决方法是使用:flexBox布局 http://www.w3c ...
- 手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单
手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩 ...
- js便签笔记(13)——jsonp其实很简单【ajax跨域请求】
前两天被问到ajax跨域如何解决,还真被问住了,光知道有个什么jsonp,迷迷糊糊的没有说上来.抱着有问题必须解决的态度,我看了许多资料,原来如此... 为何一直知道jsonp,但一直迷迷糊糊的不明白 ...
- jquery实现很简单的DIV拖动
今天用jquery实现了一个很简单的拖动...实现思路很简单 如下: 在thickbox 弹出层内实现拖拽DIV,那么得进行一下相对宽高的运算:必须加上相对于可见窗口宽高和弹出层宽高之间的差: ...
- jsonp其实很简单【ajax跨域请求】
js便签笔记(13)——jsonp其实很简单[ajax跨域请求] 前两天被问到ajax跨域如何解决,还真被问住了,光知道有个什么jsonp,迷迷糊糊的没有说上来.抱着有问题必须解决的态度,我看了许多资 ...
- css中的em 简单教程 -- 转
先附上原作的地址: https://www.w3cplus.com/css/px-to-em 习惯性的复制一遍~~~~ -------------------------------我是分界线---- ...
- 关于fullpage.js 和animate.css制作全屏简单大方的首页
附上源码: html <!DOCTYPE html><html lang="en"><head> <meta charset=" ...
- 我在阿里这仨月 前端开发流程 前端进阶的思考 延伸学习的方式很简单:google 一个关键词你能看到十几篇优秀的博文,再这些博文中寻找新的关键字,直到整个大知识点得到突破
我在阿里这仨月 Alibaba 试用期是三个月,转眼三个月过去了,也到了转正述职的时间.回想这三个月做过的事情,很多很杂,但还是有重点. 本文谈一谈工作中遇到的各种场景,需要用到的一些前端知识,以及我 ...
随机推荐
- Fortify漏洞之Dynamic Code Evaluation: Code Injection(动态脚本注入)和 Password Management: Hardcoded Password(密码硬编码)
继续对Fortify的漏洞进行总结,本篇主要针对 Dynamic Code Evaluation: Code Injection(动态脚本注入) 和 Password Management: Har ...
- Android架构组件——ViewModel
概述 ViewModel,从字面上理解的话,它肯定是跟视图(View)以及数据(Model)相关的.正像它字面意思一样,它是负责准备和管理和UI组件(Fragment/Activity)相关的数据类, ...
- [AIR] NativeExtension在IOS下的开发实例 --- Flex库项目的创建(二)
来源:http://bbs.9ria.com/thread-102038-1-1.html 上一章,我已经介绍了如果创建IOS库文件,并定义了两个方法ShowIconBadageNumber和Init ...
- The server quit without updating PID file
[root@fjgh ~]# service mysqld start Starting MySQL... ERROR! The server quit without updating PID fi ...
- Linux下使用shell脚本自动备份和移动数据到大容量存储
自动备份数据库,并将备份前一天的数据移动拷贝到存储上. 需求来源是因为linux系统层的磁盘存储容量过小,数据库自动备份之后日积月累数据越来越多,而且还不想删除旧数据.那解决方法就是在linux系统主 ...
- 使用Cloudera Manager搭建MapReduce集群及MapReduce HA
使用Cloudera Manager搭建MapReduce集群及MapReduce HA 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.通过CM部署MapReduce On ...
- [LeetCode] 0155. Min Stack 最小栈 & C++Runtime加速
题目 Design a stack that supports push, pop, top, and retrieving the minimum element in constant time. ...
- 《你又怎么了我错了行了吧》【Beta】Scrum meeting 3
第三天 日期:2019/6/26 前言: 第3次会议在女生宿舍召开(前一天晚上开的) 项目全部基本测试完成,解决了多处bug,明天终于可以拿去演示了.... 1.1 今日完成任务情况.成员贡献时间及工 ...
- 「AHOI / HNOI2017」礼物
「AHOI / HNOI2017」礼物 题目描述 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一个送给她.每个手环上各有 n 个装饰物,并且每个装饰 ...
- git常用命令总结--原创
0.git status 仓库状态1.git add 工作区-->暂存区2.git commit 暂存区-->版本库3.git log 查看日志4.git reset --hard hea ...