【后知后觉系列】css position: sticky 属性以及某些场景的使用

首发于个人 Blogcss

不知什么时候,曾经咱们认为的东西便会被打破,若是咱们不坚持着去学习,那么咱们终将会被社会所淘汰。因而我决定写《后知后觉系列》来记录一下我曾经跟不上的知识和关键点,内容不必定复杂,内容含量不必定高,也许别人已经写过一个同样的教程了,可是但愿你能从个人笔记中获取你认为重要的东西,在纷繁复杂的工做中留下一个真正极客的世界,但愿某一天这些东西都可以运用到工做当中。——XGHeavenhtml

记得先看一下目录,找到你喜欢好奇的内容去针对性阅读,毕竟我不是来写教程的。git

position: sticky 这到底是一个什么鬼?

最近公司在用 Regular 封装一个表格组件,须要实现固定表头的功能。这个是几乎全部的组件库都会实现的一个效果,因此实现方式有不少种:github

  1. 由于 thead/tr 的 position 属性是无效的,因此须要单独用 div 建立一个表头。而后设置这个表头的 position: absolute,同时 top: 0。同时这种模式下,须要用户指定每一列的宽度,保证自制的表头和下面原生的表格一一对应起来。若是不指定的话,也能够等待 dom 渲染完成以后,再测量宽度。好比 Ant Design 就是使用的这种方式。
  2. 由于上面那种方案的难点在于没法很好的保证自制表头和原生表格宽度的一致性,因此咱们组的大佬提出了使用原生 thead,监听 scroll 事件,设置 transform 属性使得表头进行偏移,从而实现 fixHeader 的问题,这种方式解决了第一个的问题,可是须要手动监听 scroll 事件,在快速滚动的状况下,可能会有必定的性能问题。并且不够优雅。若是后面的表格内容中有 position: relative 的元素,会覆盖到表头。

不论是哪一种方式,我总感受不是很完美,因而我就在思考,除了手动更新的方式,难道就没有一些比较好的方式去作。而后我就去翻看了 github 的固定表头的方式,顿时豁然开朗。因而就延伸出了这篇文章,position: sticky 属性。api

Pay Attention:后面所讲的内容就不怎么和表格固定表头相关,若是你对表格固定表头或者固定列有必定问题,能够查看网易考拉的这篇文章 《一块儿来聊聊table组件的固定列》浏览器

当第一眼看到这个熟悉的时候,第一句话就是“我 CA”,这 TMD 是什么鬼属性,position 何时有了这个属性。因而去看了 MDN 的介绍,能够理解为,这个属性是实现固定顶部最简单的实现方式dom

他实际上是一种 position:relativeposition: fixed 的结合体,必定要配合 top/right/bottom/left 的属性一块儿才有做用,设置对应方向的最小值。当大于最小值的时候,他就像 relative 同样,做为文档流的一部分,而且 top/right/bottom/left 属性也会失效。不然当小于设置的值的时候表现的像 fixed,只不过这个 fixed 再也不现对于窗口,而是相对于最近的可滚动块级元素。ide

若是你看过其余关于 sticky 的文章,大部分都会以黏贴的意思来解释他,那么很明显,确实也是这个意思,若是你以为看了其余教程可以清楚的话,那么能够不用看我这篇了,若是你没看懂的话,能够来我这里看看。性能

废话少说,咱们先来看一下如何正确使用 sticky。学习

正确的使用姿式

如下的代码预览请使用最新 Chrome 查看,或者支持 position: sticky 的浏览器查看。部分网站不支持 iframe,能够去个人 Blog 查看

  1. position: sticky 只相对于第一个有滚动的父级块元素(scrolling mechanism,经过 overflow 设置为 overflow/scroll/auto/overlay 的元素),而不是父级块元素。

    See the Pen position sticky 相对于最外面的可滚动父级 by Bradley Xu (@xgheaven) on CodePen.
  2. position: sticky 只有当设置对应的方向(top/right/bottom/left),才会有做用,而且能够互相叠加,能够同时设置四个方向。

  3. 即便设置了 position: sticky,也只能显示在父级块元素的内容区域,他没法超出这个区域,除非你设置了负数的值。

  4. position: sticky 并不会触发 BFC,简单来说就是计算高度的时候不会计算 float 元素。

  5. 当设置了 position: sticky 以后,内部的定位会相对于这个元素

    See the Pen position sticky 内部绝对定位相对于这个元素 by Bradley Xu (@xgheaven) on CodePen.
  6. 虽然 position: sticky 表现的像 relative 或者 fixed,因此也是能够经过 z-index 设置他们的层级。当这个元素的后面的兄弟节点会覆盖这个元素的时候,能够经过 z-index 调节层级。

    See the Pen position: sticky 经过 z-index 调节层级 by Bradley Xu (@xgheaven) on CodePen.

当你懂了这几个以后,其实这个属性就用起来就很简单了。

举个栗子 - 通信录列表头部

no code no bb,直接上代码。

See the Pen position sticky 通信录 Demo by Bradley Xu ( @xgheaven) on CodePen.

拓展思考

如何检测是否已经被固定?

最多见的需求就是,当还在文档流当中的时候,正常显示,可是当固定住的时候,添加一些阴影或者修改高度等操做。要想实现这个效果,第一反应可能就是手动监听 scroll 事件,判断位置,这固然是没有问题的,可是随之而来的确实性能的损耗。

最好的方式是使用 IntersectionObserver,这是一个能够监听一个元素是否显示在视窗以内的 API,具体内容见阮老师的《IntersectionObserver API 使用教程》。基本原理就是在一段滚动的头部和尾部分别添加两个岗哨,而后经过判断这两个岗哨的出现和消失的时机,来判断元素是否已经被固定。

例子详见此处

那能不能实现表格头/列固定呢?

理想很丰满,显示很骨感,由于 thead/tbody 对 position 无爱,因此也就不支持 sticky 属性,因此咱们仍是要单首创建一个头部。

后来通过网友提醒,本身又去研究了一下,发现仍是有办法作到固定表头和列的。

首先针对 Firefox,它自己就支持 thead/tbody 的 position 属性,因此能够直接经过对 thead/tbody 设置 position 来实现。而对于 Chrome 浏览器来说,能够经过设置 thead 内的 th 来实现。具体见 Demo.

See the Pen position sticky 经过设置 td 来实现固定表头 by Bradley Xu (@xgheaven) on CodePen.

而后好像就没有了,谢谢观看水水的《后知后觉系列》

相关文章
相关标签/搜索