
开发者用CSS网格实现多列不同速率滚动照片墙
来源标题:Multi-Column Different-Speed Scrolling
开发者提出一种多列不同速率滚动的画廊方案,让两列照片以不同速度滚动,营造探索感。实现上不直接改动滚动行为,而是通过随滚动值变化的方向变换制造视觉错觉,并用两列CSS网格布局搭建结构。
以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。
我脑子里一直有个想法挥之不去:当你在“画廊”里滚动浏览时,内容以什么方式从眼前掠过其实没那么重要。它可以水平滚动,可以以不同速度滚动,甚至可以反着滚——随便怎样都行。这些都不重要,因为你只是在浏览探索。滚动只是用来看到新内容的机制而已。滚动条还是应该保留,这样“还剩多少内容”的提示依然存在,但除此之外,滚动方式可以相当自由。
不同“速度”的滚动
我最初的念头是让两列照片以不同的速度滚动。第一列按正常速度滚动,页面随着你滚动而向下移动,沿途不断露出新照片。第二列则移动得更快。
我们并不打算直接干预滚动本身,那只是个障眼法。诀窍在于施加一个方向性变换,让它的值随着滚动而变化。
两列布局
首先我们需要一些列来施加效果,所以先搭一个快速的两列网格:
.photo-gallery { display: grid; grid-template-columns: repeat(2, minmax(150px, 1fr)); align-items: start; gap: 1.5rem; }Code language: CSS (css)
现在可以在里面放两列了:
<div class="photo-gallery"> <div class="photo-column-left"> <img ... /> <img ... /> ... </div> <div class="photo-column-right"> <img ... /> <img ... /> ... </div> </div>Code language: HTML, XML (xml)我们随时可以在某个断点处放弃两列布局,比如:
.photo-gallery { ... grid-template-columns: 1fr; gap: 16px; }Code language: CSS (css)
等等,那是把自定义属性用作媒体查询吗!?没错。LightningCSS 可以把它处理成“未来 CSS”。我们像未来潮人那样用 @custom-media 来设置它:
让右列滚得特别快
如我所说,我们要让其中一列(就选右列吧)以不同于另一列的速度滚动(让它更快)。诀窍在于我们随滚动施加的方向性变换,所以这里我们要利用 Scroll-Driven Animations,具体是 scroll() 那一类(之后我们再玩 view() 风格)。scroll() 类的 Scroll-Driven Animations 是更基础的那种,本质上我们能得到一个数值,用来判断元素当前滚动了多远。
.photo-column-right { /* 加点偏移纯粹为了好玩 / padding-top: 80px; animation-name: drift-up; animation-timing-function: linear; animation-fill-mode: both; animation-timeline: scroll(root block); / 整个页面 */ animation-range: 0% 100%; }Code language: CSS (css)
注意那里的 @supports 查询。并非所有浏览器都支持 Scroll-Driven Animations。不过没关系,这只是一点渐进增强的乐趣,并非关键功能。
现在我们调用了一个 @keyframes 动画,可以这样定义来实现魔法:
from { transform: translateY(12vh); to { transform: translateY(-20vh); }Code language: CSS (css)
这些数值有点“魔法数字”的味道:只是为了适应当前情况而凭感觉定的任意数字。根据额外位移的多少,你可能还需要考虑加一个 prefers-reduced-motion 查询。
额外的缩放效果
纯粹为了好玩,我们可以在每张照片上使用 view() 风格的 Scroll-Driven Animation。这样一来,在任何单张照片穿过页面的过程中,它都会缩放并略微移动(但保持原有形状)。
.photo { overflow: clip; & > img { display: block; width: 100%; height: auto; object-fit: cover; & > img { animation-name: image-drift; animation-timing-function: linear; animation-fill-mode: both; animation-timeline: view(block); animation-range: cover 0% cover 100%; }Code language: CSS (css)
现在我们有了这个 image-drift 关键帧动画,可以在里面为所欲为。
from { scale: 1.5; translate: 0 -60px; to { scale: 1; translate: 0 0; }Code language: CSS (css)
演示
这样就得到了这个效果!
能精确实现我脑中所想,感觉真满足。而且完全没用 JavaScript。
而且照片还能以 popover 形式打开,为什么不呢,这也是如今 Web 平台的又一个酷炫特性。
反向滚动
我另一个想验证的想法是,能否真的把右列的滚动方向反过来,而不只是让它滚得更快。本质上,照片会向上延伸(但保持隐藏),然后向下移动,即使滚动方向是向下的。有点怪,但无所谓。
当然,在我写这篇文章、摆弄这些想法的时候,我注意到 Codrops 五年前就做过类似的东西。你能怎么办呢?不过他们的是基于 JavaScript 的,所以这算是另一个品种。
实现思路
基本核心是一样的,我们在页面滚动时对列上的 translateY 属性做动画。但要想让它感觉对,就稍微棘手一些。比如我们想把右列往上拉,但不能拉得太远以至于一开始就看不到任何照片,所以只拉到刚好让“最后”一张图片在任何视口高度下都贴着底部的程度,然后从那里开始做动画。
整列随后使用 sticky 定位,以确保即使上方有任意高度的页头,它也能均匀滚动。但这又会干扰 view() 动画,所以“图片漂移”效果改为利用滚动位置、逐个计算每张图片的缩放和变换来恢复。这要繁琐得多,但做起来很有趣。
演示
CodePen Embed Fallback
其他好玩的!
我随手在 CodePen 上看到另外几个照片画廊的滚动实现,还要花哨得多!
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。