这篇文章发布于 2018年10月21日,星期日,01:27,归类于 CSS相关, JS API。 阅读 130509 次, 今日 15 次 47 条评论
by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=8073
本文可全文转载,个人网站无需授权,只要保留原作者、出处以及文中链接即可,任何网站均可摘要聚合,商用请联系授权。
一、引言开始言开头言
1. 这些年自己步子慢了
这些年自己在无障碍访问,SVG和Canvas这些偏小众的领域花了大量的学习精力,以至于很多前端新特性,新技术没能及时关注和了解,有CSS3领域的新属性,有JS领域的新API,包括全新的ES6/ES7语法等,相比以前的学习,步子确实慢了。比方说,本文要介绍的平滑滚动,无论是CSS还是JS,现代浏览器都提供了原生的属性或方法支持,而且差不多已经有一年时间,而我最近才知道,和数年前实时关注新技术的自己形成了明显的对比。
不过随着SVG和Canvas的基础越来越牢固,细节越来越深入,我的学习重心已经开始往广度方向转移,慢慢拾起那些遗落的麦穗。
2. 从干巴巴到又湿又滑
假设页面中有下面这一段HTML:
<a href="#" rel="internal">返回顶部</a>
帮我们点击“返回顶部”这个文字链接的时候,页面就会“唰”地一声瞬间定位到浏览器顶部,速度之快,升势之猛,以至于你没有任何反应,就像暴风雨般的爱情,让你猝不及防,脑中不断回想:“我在哪里?我是谁?我刚刚做了什么?”
所有这些反应的产生,归根结底在于我们这个滚动效果实在是太干巴巴了,机械生硬没有灵性不解风情。
人是有情感的动物,既然我们做的网页是给人用的,那自然充满情感,不要那么干巴巴,让滚动效果又湿又滑,用户体验就会好。
光滑如雪的肌肤,饱满湿润的红唇,是不是总能让人心动不已?如果我们的交互效果也能做得如此,也同样也能让用户心动。
浏览器似乎也意识到这一点,从去年年底开始,已经开始支持浏览器的原生平滑滚动定位,CSS scroll-behavior
属性和JS scrollIntoView()
方法都可以。
OK,下面开始进入正题。
二、CSS scroll-behavior与平滑滚动
scroll-behavior:smooth
写在滚动容器元素上,可以让容器(非鼠标手势触发)的滚动变得平滑。
语法
scroll-behavior: auto; scroll-behavior: smooth;
初始值是'auto'
。
我们先看一个实际的案例。
8年前“无JavaScript纯CSS实现选项卡轮转切换效果”这篇文章介绍了一种利用锚点定位纯CSS实现选项卡切换的技术(本质上是触发滚动条滚动)。
可以狠狠地点击这里:无JavaScript实现的切换效果demo
实现后的效果参见下GIF截屏:
基本功能可以满足,但有两个问题,一是由于改变location的hash实现的定位,会触发浏览器原生滚动行为,体验不好;二是选项卡内容的切换“邦邦邦”过于生硬。
于是,后来,我发明了一种基于控件元素focus触发滚动重定位的特性实现的纯CSS选项卡切换效果,在《CSS世界》这本书overflow章节有提到,您可以狠狠的点击这里:focus锚点定位和overflow的选项卡切换demo
也是纯CSS实现,没有任何JavaScript代码,相比直接利用<a>
元素的href
锚点跳转方法,此方法不会触发浏览器外部窗体的滚动,体验更上一层楼,但是还有一个问题,那就是选项卡内容切换的时候,还是“邦邦邦”这种干巴巴的效果,并没有滑来滑去那种湿湿的效果。
不要担心,现在有了CSS scroll-behavior,则平滑滚动的问题也可以解决了。您可以狠狠地点击这里:CSS scroll-behavior选项卡平滑滚动demo
相比之前干巴巴的实现,就多了这么一句CSS——scroll-behavior:smooth
:
.box {
scroll-behavior: smooth;
overflow: hidden;
}
结果一股如沐春风的交互效果扑面而来,参见下面视频截屏效果(若无效果,访问原文地址):
一行CSS就可以锦上添花。
更简单更实际的用途
其实scroll-behavior
的使用没有那么多花头,你就记住这么一句话——
凡是需要滚动的地方都加一句scroll-behavior:smooth就好了!
你别管他用不用得到,也不用管浏览器兼容性如何,你都加上。这就像一个不要钱的免费抽奖,没有中奖,没关系,又没什么损失,中奖了自然好,锦上添花!scroll-behavior:smooth
就是这种尿性。
举个例子,在PC浏览器中,网页默认滚动是在<html>
标签上的,移动端大多数在<body>
标签上,于是,我加上这么一句:
html, body { scroll-behavior:smooth; }
此时,点击下面这个“返回顶部”链接,就会平滑滚动到顶部(真·实时效果,可以点击尝试)。
HTML代码如下:
<a href="#">返回顶部</a>
从这一点来看,业界浏览器的CSS reset都可以加上这么一条规则:
html, body { scroll-behavior:smooth; }
三、JS scrollIntoView与平滑滚动
DOM元素的scrollIntoView()
方法是一个IE6浏览器也支持的原生JS API,可以让元素进入视区,通过触发滚动容器的定位实现。
随着Chrome和Firefox浏览器开始支持CSS scroll-behavior
属性,顺便对,scrollIntoView()
方法进行了升级,使支持更多参数,其中一个参数就是可以使滚动平滑。
语法如下:
target.scrollIntoView({ behavior: "smooth" });
我们随便打开一个有链接的页面,把首个链接滚动到屏幕外,然后控制台输入类似下面代码,我们就可以看到页面平滑滚动定位了:
document.links[0].scrollIntoView({ behavior: "smooth" });
如下视频截屏:
其它:
scrollIntoView()
升级后的方法,除了支持'behavior'
,还有'block'
和'inline'
等参数,有兴趣可以参阅MDN相关文档。- 如果我们的网页已经通过CSS设置了
scroll-behavior:smooth
声明,则我们直接执行target.scrollIntoView()
方法就会有平滑滚动,无需再额外设置behavior
参数。例如,如果你是在鑫空间原站浏览的此文章,打开控制台,执行下面代码,就可以看到平滑滚动效果了:document.forms[0].scrollIntoView();
四、JS平滑滚动向下兼容处理
JS实现平滑滚动并不难,jQuery中animate()
方法:
scrollContainer.animate({ scrollTop: 0 });
或者使用requestAnimationFrame API这类原生JS也能实现。例如下面这个我速写的个方法:
/** @description 页面垂直平滑滚动到指定滚动高度 @author zhangxinxu(.com) */ var scrollSmoothTo = function (position) { if (!window.requestAnimationFrame) { window.requestAnimationFrame = function(callback, element) { return setTimeout(callback, 17); }; } // 当前滚动高度 var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; // 滚动step方法 var step = function () { // 距离目标滚动距离 var distance = position - scrollTop; // 目标滚动位置 scrollTop = scrollTop + distance / 5; if (Math.abs(distance) < 1) { window.scrollTo(0, position); } else { window.scrollTo(0, scrollTop); requestAnimationFrame(step); } }; step(); };
使用的是自己私藏缓动动画JS小算法,滚动先快后慢。
使用如下,例如,我们希望网页平滑滚动到顶部,直接:
scrollSmoothTo(0);
就可以了。
难的是如何支持平滑滚动的浏览器原生处理,不支持的浏览器还是使用老的JS方法处理。
我是这么处理的JS如下判断:
if (typeof window.getComputedStyle(document.body).scrollBehavior == 'undefined') {
// 传统的JS平滑滚动处理代码...
}
这样就可以无缝对接了。
五、结语结尾语结束语
没有个人特质的文章就像没有灵魂的机器一样。怀念张含韵的照片,家里领导不放心,怕侵犯版权找上门,都给下掉了,现在的那些美女照片,就像白开水一样,索然无味……
我琢磨着要换个角色或者标签,例如……一匹马!
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=8073
(本篇完)
- 了解web前端领域的undefined behavior未定义行为 (0.414)
- 如何使用Tween.js各类原生动画运动缓动算法 (0.308)
- CSS3动画那么强,requestAnimationFrame还有毛线用? (0.276)
- 小tips: 元素focus页面不滚动不定位的JS处理 (0.196)
- 小tip: 子元素scroll父元素容器不跟随滚动JS实现 (0.170)
- 尝试使用JS IntersectionObserver让标题和导航联动 (0.170)
- 使用document.scrollingElement控制窗体滚动高度 (0.161)
- 大侠,请留步,要不过来了解下CSS Scroll Snap? (0.147)
- CSSOM视图模式(CSSOM View Module)相关整理 (0.138)
- 几个常见功能重合DOM API的细节差异 (0.138)
- 无JavaScript纯CSS实现选项卡轮转切换效果 (RANDOM - 0.006)
我看的是盗版吗?document.forms[0].scrollIntoView();没有平滑效果
滚动的时间能定义吗
暂时还不能。
学到了学到了,特别是最后 没有个人特质的文章就像没有灵魂的机器一样
点醒了我,总感觉我的文章缺少了点什么,现在找到了
scrollIntoView在ios上不生效啊,看文章说不能加参数,加了参数会滚不动
感谢张老师的这篇文章,解决了大问题!
鑫哥,我现在出现一个问题。
项目中使用了LazyLoadImage, ‘react-lazy-load-image-component’
当页面第一次加载时,使用scrollIntoView()滑动到底部时,触发到了LazyLoadImage 加载图片,此时我发现页面会突然滑动回去。
但是当图片资源都加载完了,这个问题又不会出现了。请问是什么原因导致的?要怎么处理呢?
实用下来最大的问题就是滚动速度不可控,太慢了……我想用于移动端的无限上拉信息流,但是只是7屏的时间就超过1s了,反而降低了用户体验?
添加了这个属性之后,有什么办法知道滚动动画什么时候结束了呢?
滚10px和滚1000px的时间肯定不一样,定时器是不行的.
scroll-behavior:smooth;
和
jquery的animate一起使用,在chrome中会影响animate动画效果
向下兼容中 position的具体值怎么取
这些属性移动端都兼容么
向下兼容中 position的具体值怎么取
回到顶部
每每看到那张经典张含韵照片总会想到你,所以没有了张含韵,总感觉菜里缺了盐般毫无灵魂
基于控件元素focus触发滚动 横向滚动怎么弄啊,每次只会滚一半
好像在真机上scrollIntoView behavior就不起作用了 ,没有滚动效果了,直接跳到视图
scrollIntoView behavior 在ios上有兼容性。安卓端是可以的。
可以引入 smoothscroll.js
https://cdnjs.cloudflare.com/ajax/libs/iamdustan-smoothscroll/0.4.0/smoothscroll.min.js
楼主,小弟在实际开发中遇到一个问题,虽然问题已解决,但还是不知道问题的根本原因。
问题如下:
在页面根节点加了html, body { scroll-behavior:smooth; },同时,在js里运用requestAnimationFrame+scrollTo()实现平滑滚动(不判断浏览器是否支持scroll-behavior:smooth;)会出现大于600ms的延迟?但去掉requestAnimationFrame后就不会出现延迟了!
只联想到了一种场景,不知道能不能解决你的问题,在大神的书里看到过类似的延迟,就是你开始滑动的高度可能很大,但是你实际要滑动的空间比较小,但是滑动是从很大的高度开始的,也就是说从很大空间到你要滑动的空间相差的高度比较大,造成了一种滑动无效的情况,也就是“延迟”这种问题了。
没有张含韵的你不是你
纵享湿滑
重点:怀念张含韵的照片
这个属性在ctrl+f搜索的时候也有用啊。
我发现,只能在html标签上使用生效,其他标签无效呀
非常棒
你家领导怕你看多了会爱上她
旭哥,scroll-behavior:smooth这个触发后速度有点慢,有什么好的办法吗
怀念张含韵
旭哥,你养宠物的么?
养鱼~
养肥了就吃了
眼光长远的不行
挺好的呀
第三部分,第三段文字把首个链接滚动到屏幕“外”,应该是屏幕内吧
总感觉文中一段话好污????
兄弟是说从“干巴巴到”此处省略4个字?
我觉得主角换成 琦玉老师 不错,一种与生俱来的强者姿态
我来凑人气的,张含韵的不让放,但是可以不以放周杰伦的图片啊,版权那边我来搞定
怕侵权?我差点就信了
前端高手啊,厉害啊
*{ scroll-behavior: smooth;}
加上这个岂不是更爽吗。html,body覆盖不到子DIV中。
恩,性能也很爽。
我的搜狗急速模式居然不支持这个属性….看来谷歌内核版本还是不够高
有这个担心是不错的
c00不是挺好的
之前总感觉少了什么,原来是张含韵的照片