百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

七爪源码:纯 CSS 和 JS 的原生平滑滚动

myzbx 2025-02-27 15:57 6 浏览

纯 CSS 和 JS 的原生平滑滚动

你想要一个平滑的滚动吗? 忘记 JQuery,我们已经过去了。 让我向您介绍我们的原生平滑滚动工具。


CSS 滚动行为

CSS scroll-behavior 属性接受三个值之一 - 实际上是两个值,因为其中一个已被弃用。

  1. scroll-behavior: auto 是我们已经习惯的默认即时滚动行为。
  2. scroll-behavior:instant 与 auto 相同,这就是它被弃用的原因。 如果你想要它,只需使用自动。
  3. scroll-behavior: smooth 在以编程方式触发滚动事件时应用平滑过渡。

我说“以编程方式触发”是因为它不会平滑滚动鼠标滚轮。

以编程方式触发滚动事件的一些方法是:

Bash
-    Window.scrollTo()
-    Window.scrollBy()
-    Element.scrollTo()
-    Element.scrollBy()
-    Element.scrollIntoView()
-    Element.scrollLeft = x
-    Element.scrollTop = y

我们将分别探索这些方法。


(注)Window.scroll() 和 Element.scroll()

也许你已经注意到我没有提到 scroll() 方法。

这是因为 Window.scroll() 和 Element.scroll() 实际上是与 Window.scrollTo() 和 Element.scrollTo() 相同的方法。为避免重复内容,我将仅参考 scrollTo()。在实践中,您可以使用任何一种,只需选择一个并保持一致。


Window.scrollTo() 和 Element.scrollTo()

此方法非常适合滚动到绝对坐标。如果您有要将用户滚动到的位置的 x 和 y 坐标,您可以简单地调用 window.scrollTo(x, y) ,它会尊重页面的 CSS 滚动行为。

这同样适用于可滚动元素。您只需调用 element.scrollTo(x, y) ,它就会尊重元素的 CSS 滚动行为。

这个方法还有一个新的签名,它使用一个对象而不是两个数字参数,通过这个新的签名,我们可以显式地设置我们的滚动行为。

Bash
// For window
window.scrollTo({
  left: x,
  top: y,
  behavior: 'smooth'
});
// For element
const el = document.querySelector(...);
el.scrollTo({
  left: x,
  top: y,
  behavior: 'smooth'
});


Element.scrollLeft 和 Element.scrollTop

设置元素 .scrollLeft 和 .scrollTop 属性与使用坐标调用 Element.scrollTo() 相同。 它将尊重元素的 CSS 滚动行为。

const el = document.querySelector(...);
const x = 100;
const y = 500;
// Setting .scrollLeft and .scrollTop with smooth scroll
el.style.scrollBehavior = 'smooth';
el.scrollLeft = x;
el.scrollTop = y;
// Is the same as calling Element.scrollTo()
el.scrollTo({ left: x, top: y, behavior: 'smooth' });


(注)负元素.scrollLeft

如果你的元素文本的方向是 rtl,scrollLeft = 0 表示水平滚动的最右边位置,并且随着你向左移动,值会减小。

对于宽度为 100px,可滚动宽度为 500px,方向为 rtl 的可滚动元素,最左边的位置是 scrollLeft = -400。

const scrollable = document.querySelector('#scrollable');
const output = document.querySelector('#output');
const updateOutput = () => {
  output.textContent = `scrollLeft: ${scrollable.scrollLeft}`;
};
updateOutput();
scrollable.addEventListener('scroll', updateOutput);


Window.scrollBy() 和 Element.scrollBy()

此方法与 Window.scrollTo() 或 Element.scrollTo() 具有完全相同的签名。 它接受 x 和 y 作为两个数字参数或作为具有可选 left、top 和 behavior 属性的对象的单个参数。

这里的区别是我们不是传递绝对坐标,而是相对值。 如果我们 scrollBy({ top: 10 }),我们从当前位置向下滚动 10 个像素,而不是从页面开头向下滚动 10 个像素。

// For window
window.scrollBy({ top: 10 }); // Scroll 10px down
window.scrollBy({ left: 20 }); // Then 20px to the right
window.scrollBy({ top: 50 }); // And then 50px down
// For element
const el = document.querySelector(...);
el.scrollBy({ top: 10 }); // Scroll 10px down
el.scrollBy({ left: 20 }); // Then 20px to the right
el.scrollBy({ top: 50 }); // And then 50px down


(注) Window.scrollByLines() 和 Window.scrollByPages()

Firefox 更进一步,实现了滚动多行或多页的方法。 这是一个仅适用于 Firefox 的非标准功能,因此您可能不想在生产中使用它。

通过将 100vh(用于页面)和 1rem(用于行)转换为像素并将该值传递给 Window.scrollBy(),您可以在所有主要浏览器中实现类似的效果。

const toPixels = require('to-px'); // From NPM
const page = toPixels('100vh');
window.scrollBy(0, page); // window.scrolByPages(1)
const line = toPixels('1rem');
window.scrollBy(0, line); // window.scrolByLines(1)


Element.scrollIntoView()

但大多数时候,我们并不关心任何硬编码的坐标,我们只想将用户滚动到屏幕上的特定元素。 这可以通过 Element.scrollIntoView() 轻松(更明确地)完成。

可以不带参数调用此方法,它将滚动页面(尊重 CSS 滚动行为)直到元素在顶部对齐(除非元素在页面底部,在这种情况下,它会 尽可能滚动)。

Some space
Our element
More space
const target = document.querySelector('#target');
target.scrollIntoView();

您可以通过传递布尔值或对象来进一步自定义元素在视图中的位置。

const el = document.querySelector(...);
// Default, aligns at the top
el.scrollIntoView(true);
// Aligns at the bottom
el.scrollIntoView(false);
// Aligns vertically at the center
el.scrollIntoView({ block: 'center' });
// Vertical top and horizontal center
el.scrollIntoView({ block: 'start', inline: 'center' });
// Vertical bottom and horizontal right
el.scrollIntoView({ block: 'end', inline: 'end' });
// Vertical center and smooth
el.scrollIntoView({ block: 'center', behavior: 'smooth' });
// Vertical nearest
el.scrollIntoView({ block: 'nearest' });

当使用一个对象来定义元素的位置时,注意 block 是指垂直放置,而 inline 是指水平放置。此外,“最近”的位置可以是顶部/左侧或底部/右侧,以最近的为准,如果元素已经在视图中,它也可以是空的。


浏览器支持

{关于浏览器支持} 在撰写本文时,所有主流浏览器(Safari 除外)都支持平滑滚动和本文中描述的滚动方法。

如果你需要更多的保证,我在我的项目中使用了一个非常好的平滑滚动 polyfill。它填充了 scroll()、scrollTo()、scrollBy()、scrollIntoView() 和 CSS 滚动行为。它不支持通过设置 scrollLeft/scrollTop 来平滑滚动,也不支持 scrollIntoView() 选项(它总是在顶部对齐元素)。

如果你有更多的好奇心,我强烈建议你研究一下 polyfill 的源代码,总共不到 500 行。我做了一个 PR 来稍微改进文档,你可能会发现代码更容易理解。


祝你有美好的一天,很快见到你。

相关推荐

【暗区突围】盘点那些“经久不衰”的弹挂,经典永不过时!

暗区突围到现在都S5赛季了,大家平时常用的弹挂基本上还是那么几个,这期就来盘点下那些"经久不衰"的弹挂。·TOP1.BH步兵胸挂:它经常会和"中型登山包"一起搭配食用嫖仔们最爱的神仙套装组合。BH弹挂...

一台离谱的奥迪S5(奥迪s5l)

都说德系车做工严谨,但是一台奥迪S5,竟然错装了奥迪S4的座椅,这种离谱的事你敢信吗?如果不是当事人手头有确凿的证据,连我都不敢相信。这位S5的车主名叫石头,上海本地人,之前开的是雷克萨斯is300,...

最快上海车展见面 全新奥迪S5 Sportback谍照曝光

一直以来奥迪旗下S系列车型的实力一直不容小视,无论是竞争对手还是车主,对每次奥迪推出S系列车型都非常关注。尤其是S5车型,凭借极具引力的外观设计、实用性、豪华和性能备受好评,而S5一直被称为“万金油”...

苹果 Watch Series 6 智能手表开箱

因为最近准备健身所以就入手了。ApplewatchS6京东自费购买,活动价2299,加上京东礼品券入手价2157。为什么没选择SE呢?目前6代这个价格只比SE贵100多块钱,相比SE那屏幕有所升...

直降4万8想买特斯拉Model Y,懂车帝3D试驾告诉你体验如何

开年第一周特斯拉价格大跳水,ModelY长续航全轮驱动版售价直降4万8,让不少心仪特斯拉的粉丝心潮澎湃,但受限于春节,多数年轻人很难到特斯拉体验店专程试驾ModelY。最近,懂车帝就开通了全新的3...

视频:三星S4运行安卓5.0第二弹,新的插件

IT之家(www.ithome.com):视频:三星S4运行安卓5.0第二弹,新的插件IT之家讯,想必使用三星手机的用户都在焦急地等待着Android5.0的更新,然而目前三星并没有给出任何确切的升...

应用更轻松 玩转三星Galaxy J智能管理器

2015-07-2305:28:00作者:邱鑫三星GalaxyJ7的智能管理器包括电源管理、存储管理、RAM管理、设备安全管理四大项管理。这四项管理也是人们平时比较需要的智能机设定应用,能够很好...

凶猛的巨兽 LOL迷失之牙S5大型攻略

这里依然是想跳票就跳票的啃包菜的猫,LPL春季赛已经落下帷幕,EDG获得了三连冠,风风火火的比赛也告一阶段,话说决赛的比赛还真是精彩纷呈啊...虽然打了很久。马上到了万众期待欢乐的51小长假了,不知道...

Gif已out !三分钟教你做动图特效(动图特效素材)

360搜索前段时间推出过一款“拍题神器”,引发广泛反响,包括央视、北京卫视等主流媒体相继对此功能进行了报道,正值外界还在对“拍题神器”激烈讨论之际,360移动搜索再推新功能,“玩图”一经推出之后便迅速...

苹果1278 820-2879-B料板多种故障的维修

以下维修技术案例由迅维快修小编整理自迅维论坛,本文作者:迅维ID(Jialin116)苹果1278820-2879-B这块主板原来是准备做料板用的,我看成色还可以,为了挑战一下自己的维修能力,就尝试...

松下发布模块化摄影机BGH1(松下摄像机新品)

日前,松下宣布推出第一款BOX摄影机DC-BGH1,国内将于10月底正式发布。基于M43系统标准,新型LUMIXBGH1充分利用了高移动性和广泛并且可互换镜头阵容的优势,结合了所有松下通过发展的在专...

博朗新款S5剃须刀值不值得买?深度评测你来看看

前言大家好,我是聚灵阵主。今天我准备整理分享一下我刚刚到手的博朗新款S5剃须刀的使用评测。博朗是往复式剃须刀的代表性品牌,在过去的几十年中适中以精湛的技术创新引领着往复式剃须刀的发展。相对于旋转式剃须...

曝iQOO 13主打性能、下调影像,屏幕和快充都有亮点

十月将至,各家新机爆料不断出现,热闹非凡昨日,iQOO产品经理@戈蓝V发文预热了iQOO13的屏幕信息。称其将全球首发BOE(京东方)最新一代发光材料,在显示效果、护眼技术、户外亮度、操控体...

阿布复盘S5的MSI:EDG还有大招没用 Faker原来上了Kkoma的当?

大家好,我是小老弟。这一仗好像直接把胖爹的腰打断了……最近LPL比赛未开,官方直播间里轮播起了过往的经典比赛,前EDG教练则在回顾EDG和SKT那场经典MSI决赛比赛中,与观众一起复盘了当时的一些比赛...

阿布复盘S5的MSI:EDG还有一手准备至今没有用

大家好,我是小老弟。这一仗好像直接把胖爹的腰打断了……最近LPL比赛未开,官方直播间里轮播起了过往的经典比赛,前EDG教练则在回顾EDG和SKT那场经典MSI决赛比赛中,与观众一起复盘了当时的一些比赛...