Sticky定位

Author : lovecicy

先来看个例子,在Safari或者火狐下打开哦:

See the Pen CSS Sticky headers by YuC (@yuuuuc) on CodePen.

或者再看个例子:HTML5Rocks

先来解释下sticky定位的作用是什么:当用户滚动到某一位置时,某个元素就固定在页面上了。

这样的场景非常常见,比如iOS或者安卓的联系人,当你滚动时,对应的字母总在最顶端,当下一个字母上来时,会将前一个字母顶上去;或者BootStrap的文档页面,初始状态下,右边的菜单会随页面滚动而滚动,但是当菜单顶部滚动到页面顶部时,再往下滚,菜单就固定在页面顶部了。

通常(现在),我们的做法是使用js来监听用户的滚动事件,当滚动到某一高度,就将特定的元素设置为position:fixed。类似下面的做法:

<style>
.sticky {
  position: fixed;
  top: 0;
}
.header {
  width: 100%;
  background: #F6D565;
  padding: 25px 0;
}
</style>

<div class="header"></div>

<script>
var header = document.querySelector('.header');
var origOffsetY = header.offsetTop;

function onScroll(e) {
  window.scrollY >= origOffsetY ? header.classList.add('sticky') :
                                  header.classList.remove('sticky');
}

document.addEventListener('scroll', onScroll);
</script>

这样的做法非常简单,但是如果你要对非常多的元素进行这样的操作,那将会是灾难性的。

为什么JS的做法不够好呢?

Something else to consider is that more and more browsers are implementing hardware accelerated scrolling to improve performance. The problem with this is that on JS scroll handlers are in play, browsers may fall back into a slower (software) mode. Now we’re no longer running on the GPU. Instead, we’re back on the CPU. The result? User’s perceive more jank when scrolling your page.

越来越多的浏览器实现了硬件加速滚动来改善性能。当JS的scroll处理函数在处理时,浏览器又回到了低速模式:不再使用GPU,而是使用CPU,结果是用户体验的下降。

而且,正如John大神(所说)[http://ejohn.org/blog/learning-from-twitter/],twitter就是因为scroll事件的处理函数,导致了页面无响应。

因此,sticky的出现就非常有必要了,我们先来看看它的定义,出自MDN:

Sticky positioning is a hybrid of relative and fixed positioning. The element is treated as relative positioned until it crosses a specified threshold, at which point it is treated as fixed positioned.

Sticky定位是相对定位和固定定位的混合体。元素被某个阈值之前,被当做相对定位的元素,在达到阈值之后,会被当做固定定位的元素。

但是对于上面的定义,我认为有错误,sticky定位应该是static定位和fixed定位的混合,在某个阈值之前,你对该元素设置的定位属性,即top,left,right,bottom,是不生效的,表现如同static定位,而当达到阈值之后,才表现为固定定位。而且它的固定定位不是相对于视窗,而是相对于最近的定位祖先元素。

用法也很简答,和绝对定位类似:

#one { position: sticky; top: 10px; }

当然,这还是一个处在实验阶段的API,目前只有火狐与Safari支持这个属性,并且Safari是带有-webkit前缀的哦。

浏览器支持情况: Can I Use
参考:
HTML5Rocks
MDN

standard

Have your say