Scroll-LinkedAnimations 规范是 CSS 即将推出的实验性补充。 使用规范提供的@scroll-timelineat-rule和animation-timeline属性css3 旋转木马,您可以通过滚动来控制常规CSS动画的时间位置。
在本文中,我们将了解一些实际用例css3 旋转木马,其中滚动链接的动画代替典型的 JavaScript 技巧会派上用场。
本文中描述的 CSS 功能仍处于实验阶段,尚未最终确定。 在撰写本文时,不仅 Chromium ≥ 89 浏览器启用了 #experimental-web-platform-features 标志,其他浏览器也不支持此功能。
CSS 滚动链接动画,快速入门手册
使用 CSS 滚动链接动画,您可以通过滚动来驱动 CSS 动画:当您在可滚动容器中向下或向上滚动时,链接的 CSS 动画将向前或向后。 最重要的是,这一切都在合成器的主线程上运行。
要实现基本的滚动链接动画,您需要三件事。
CSS 动画滚动时间线两个 CSS 动画之间的链接
这是我们已经知道的普通CSS动画。
@keyframes adjust-progressbar {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
正如您通常所做的那样,将其附加到具有动画属性的元素。
#progressbar {
animation: 1s linear forwards adjust-progressbar;
}
滚动时间线
滚动时间线允许我们将滚动距离映射到动画进度。 在 CSS 中,我们用 CSS @scroll-timelineat-rule 来描述这一点。
@scroll-timeline scroll-in-document-timeline {
source: auto;
orientation: vertical;
scroll-offsets: 0%, 100%;
}
该 at 规则由描述符组成,包括。
源代码描述了可滚动元素,其滚动会触发激活并驱动时间线的进度。 默认情况下,这是整个文档。 方向确定应触发动画的滚动方向。 默认情况下,这是垂直的。 滚动偏移属性是一个关键字段,它描述了动画应该激活的范围。 它可以是绝对的(例如比率和宽度)或基于元素的。
原始规范版本还要求您设置时间范围描述符。 该描述符已被删除,并将手动接管链接动画的动画持续时间。 您可能一直在演示中看到它的踪迹,但您可以放心地忽略它。
两者之间的联系
为了将 @scroll-timeline 与 CSS 动画联系起来,我们使用新的animation-timeline CSS 属性并让它引用时间轴的名称。
#progressbar {
animation: 1s linear forwards adjust-progressbar;
animation-timeline: scroll-in-document-timeline; /* THIS! */
}
通过此设置,调整进度条动画不会在页面加载时手动运行,而是在我们向上滚动页面时前进。
有关 @scroll-timeline 的更深入介绍,请参阅我未来的滚动链接动画系列的第 1 部分和第 2 部分。
第一篇文章更详细地研究了每个描述符/属性,用反例对其进行了解释,然后介绍了许多更有趣的演示。
第二篇文章更深入地介绍了基于元素的倾斜,它允许我们驱动元素出现在滚动端口并在滚动时消失的动画。
使用基于元素的倾斜来为 CSS 滚动链接设置动画的反例。
实际用例
不仅仅是里面的进度演示,还有一些滚动链接动画可以替代用 JavaScript 实现的通用解决方案的用例或场景。
视差标题图像显示/隐藏打字动漫轮播指示器滚动间谍视差脚注
Scroll-LinkedAnimations 的一个典型用例是视差效果,其中页面的多个部分具有不同的滚动速率。有一种方法可以仅使用 CSS 创建这种类型的效果,但它需要
受 FirewatchHeader 的启发,我使用 CSS 创建了这个版本的滚动时间线 - 它使用了前面提到的转换 hack。
CodePen 嵌入后备
与原始演示文稿相比。
每个不同的图层都使用相同的滚动时间线:滚动距离为 100vh。
@scroll-timeline scroll-for-100vh {
time-range: 1s;
scroll-offsets: 0, 100vh;
}
.parallax__layer {
animation: 1s parallax linear;
animation-timeline: scroll-for-100vh;
}
当我们向上滚动时,各层之间的连接距离有所不同。
@keyframes parallax {
to {
transform: translateY(var(--offset));
}
}
.parallax__layer__0 {
--offset: 100vh;
}
.parallax__layer__1 {
--offset: 83vh;
}
.parallax__layer__2 {
--offset: 67vh;
}
.parallax__layer__3 {
--offset: 50vh;
}
.parallax__layer__4 {
--offset: 34vh;
}
.parallax__layer__5 {
--offset: 17vh;
}
.parallax__layer__6 {
--offset: 0vh;
}
当最顶层的通信距离较远时,它们的通信速度似乎比较低层更快,从而实现视差效果。
图像显示/隐藏
滚动链接动画的另一个重要用途是图像显示。
默认情况下,图像的不透明度为 0 并使用 [clip-path](#the-new-clip-path):
#revealing-image {
opacity: 0;
clip-path: inset(45% 20% 45% 20%);
}
在最终状态下,我们希望图像完全可见,因此我们发送动画的结束帧来反映这一点。
@keyframes reveal {
to {
clip-path: inset(0% 0% 0% 0%);
opacity: 1;
}
}
通过使用倾斜量作为滚动时间线,我们可以使其在图像本身滑入视图时出现。
@scroll-timeline revealing-image-timeline {
scroll-offsets:
selector(#revealing-image) end 0.5,
selector(#revealing-image) end 1
;
}
#revealing-image {
animation: reveal 1s linear forwards;
animation-timeline: revealing-image-timeline;
}
无法遵循这种基于元素的倾斜? 这个可视化/工具已经为你解决了。
打字动漫
因为 CSS 滚动时间轴可以与任何现有的 CSS 动画绑定,所以您基本上可以获取任何 CSS 动画演示并对其进行修改。 以打字动漫为例。
通过添加滚动时间线和动画时间线属性,可以将其调整为“滚动时键入”。
CodePen 嵌入后备
请注意,为了创建某种滚动状态,还给出了高度,即 300vh。
使用不同的动画,可以轻松调整内部代码以创建滚动缩放效果。
我可以看到这两个对于文章介绍非常有用。
轮播/滑块指示器
轮播的组件之一(又名滑块)是一个指示器,显示它包含多少个魔板以及当前处于活动状态的魔板。 这通常是使用 shell 完成的。
我们将能够使用 CSS 滚动时间轴来完成此操作,如 Fabrizio Calderan 创建的演示所示。
活动 shell 通过 .slidernav::before 传递,并设置一个动画以使其连接到其他 shell。
/* Styling of the dots */
.slider nav::before, .slider a {
inline-size: 1rem;
aspect-ratio: 1;
border-radius: 50%;
background: #9bc;
}
/* Positioning of the active dot */
.slider nav::before {
content: "";
position: absolute;
z-index: 1;
display: block;
cursor: not-allowed;
transform: translateX(0);
animation: dot 1s steps(1, end) 0s forwards;
}
/* Position over time of the active dot */
@keyframes dot {
0%
{ transform: translateX(0); }
33%
{ transform: translateX(calc((100% + var(--gap)) * 1)); }
66%
{ transform: translateX(calc((100% + var(--gap)) * 2)); }
100%
{ transform: translateX(calc((100% + var(--gap)) * 3)); }
}
通过将 @scroll-timeline 附加到滑块,代表活动状态的点可以在滚动时进行通信。
@scroll-timeline slide {
source: selector(#s);
orientation: inline;
}
.slider nav::before {
/* etc. */
animation-timeline: slide;
}
因为动画中添加了steps()函数,所以只有在滑块单击到其位置后才能连接该点。当您删除它时,滚动时点的连接方式会变得更加清晰
这感觉就像 Christian Shaefer 的纯 CSS 轮播中最后缺失的一块。
滚动间谍
早在 2020 年初,我创建了一个具有滚动活动状态的粘性目录。 创建演示的最后部分是在向下/向上滚动文档时使用 IntersectionObserver 设置目录 (ToC) 中的活动状态。
与之前演示的轮播指示器不同,我们不能简单地连接一个点来达到目的,因为目录中的文本是要调整的。 为了处理这些情况,我们需要将两个动画附加到目录的每个元素。
第一个动画是当适当的部分出现在文档的顶部边缘时以可视方式激活目录项。 第二个动画是当相应部分滑出文档底部边缘的视图时,以视觉方式停用目录项。
.section-nav li > a {
animation:
1s activate-on-enter linear forwards,
1s deactivate-on-leave linear forwards;
}
由于我们有两个动画,因此我们还需要为内容的每个部分创建两个滚动时间线。 以#introduction部分为例。
@scroll-timeline section-introduction-enter {
source: auto;
scroll-offsets:
selector(#introduction) end 0,
selector(#introduction) end 1;
}
@scroll-timeline section-introduction-leave {
source: auto;
scroll-offsets:
selector(#introduction) start 1,
selector(#introduction) start 0;
}
一旦这两条时间线与两部动漫联系起来,事情就会按计划进行。
.section-nav li > a[href"#introduction"] {
animation-timeline:
section-introduction-enter,
section-introduction-leave;
}
终于
我希望我已经让您相信 CSS 可滚动链接动画规范所提供的潜力。 不幸的是,目前它仅在基于 Chromium 的浏览器中受支持,隐藏在徽标旁边。