请使用firefox,chrome等最新浏览器浏览本站。

position:sticky实现粘性布局

css3 阿豹 403次浏览 0个评论 扫描二维码

网站中,通常我们会把用户最常用到或者我们希望用户注意到的内容一直展现在窗口的可视区域,让用户能够一眼就看到。经常用到一种页面滚动然后元素固定在窗口的某个位置的布局方式。要实现这种布局通常我们会使用js监听window的scroll事件,当需要固定的元素滚动到窗口顶部时,把元素的position属性设置为fixed,否则,取消fixed,简单的js代码如下:

var nav = document.querySelector('.nav');
var navOffsetY = nav.offsetTop;
function onScroll(e) {
    window.scrollY >= navOffsetY ? nav.classList.add('fixed') : nav.classList.remove('fixed'); 
}
window.addEventListener('scroll', onScroll);

上面的实现在桌面浏览器的表现还是挺好的,但是在移动端浏览器上效果就显得不那么平滑了,特别是ios。iOS下的浏览器会在页面滚动的时候,暂停所有js的执行,直到滚动停止才会继续去执行js(注意暂停了所有js的执行,所以考虑用 setTimeout 或 setInterval 也是没有用的)
所以页面滚动时, scroll 事件在iOS的浏览器下并不会持续被触发,而是在页面滚动停止后,才会去触发一次 scroll 事件。 在Android 2.3及以下的版本的浏览器 scroll 事件的响应也是跟iOS一样。而Android 2.3以上的版本中虽然有部分浏览器能持续的触发 scroll 事件,但由于移动设备上惯性滚动的原因, scroll 事件的回调函数执行渲染Dom频率还是赶不上滚动的频率,所以即使是在高版本的Android下,滚动快了,还是会看到原来fixed的元素闪跳归位。

使用position:sticky

position:sticky的表现上像是position:fixed和position:relative的结合体,设置了position:sticky的元素,特征如下:
1.元素不会脱离文档流,并保留元素在文档流中占位的大小
2.元素在容器中被滚动超过指定的偏移值时,元素在容器内固定在指定位置
3/元素固定的相对偏移是相对于离它最近的具有滚动框的祖先元素,如果祖先元素都不可以滚动,那么是相对于viewport来计算元素的偏移量

查看兼容性

要实现该效果兼容,我们可以再支持sticky的浏览器上使用。不支持的浏览器使用js实现:

css:

.sticky {
    position: -webkit-sticky;
    position: sticky;
    top: 0;
}
.fixed {
    position: fixed;
    top: 0;
}

js:

// 判断是否支持sticky属性
function isSupportSticky() {
    var prefixTestList = ['', '-webkit-', '-ms-', '-moz-', '-o-'];
    var stickyText = '';
    for (var i = 0; i < prefixTestList.length; i++ ) {
        stickyText += 'position:' + prefixTestList[i] + 'sticky;';
    }
    // 创建一个dom来检查
    var div = document.createElement('div');
    var body = document.body;
    div.style.cssText = 'display:none;' + stickyText;
    body.appendChild(div);
    var isSupport = /sticky/i.test(window.getComputedStyle(div).position);
    body.removeChild(div);
    div = null;
    return isSupport;
}
var nav = document.querySelector('.nav');
if (isSupportSticky()) {
    nav.classList.add('sticky');
} else {
    var navOffsetY = nav.offsetTop;
    function onScroll(e) {
        window.scrollY >= navOffsetY ? nav.classList.add('fixed') : nav.classList.remove('fixed'); 
    }
    window.addEventListener('scroll', onScroll);
}

喜欢 (9)or分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到