查看原文
其他

现代CSS:纯 CSS 实现苹果风格(Apple-style)的图片滚动器

小懒 FED实验室 2024-02-12

前端开发者要实现类似苹果风格(Apple-style)的图片滚动器,通常会采用 JavaScript 来监听 Scroll 事件来实现。我们知道,在 scroll 事件中频繁获取 scrollTop 可能会引起频繁的重绘和重排,导致页面和动画卡顿。本文仅使用 Scroll-driven Animations、Scroll Snapping、 clamp()object-view-box等现代 CSS 来实现同样效果。

核心现代 CSS 属性如下:

  • Scroll-driven Animations
  • Scroll Snapping
  • object-view-box

1.效果预览

2.核心知识点介绍

2.1.Scroll-driven Animations

Scroll-driven Animations:是由滚动驱动的动画,是一种常见的交互模式,在提升网站的用户体验方面,扮演着非常重要的角色。Scroll-driven Animation 规范中定义了两种新的 timeline,可以指定动画在元素滚动条滚动时运行,@keyframes 的进度也就跟着滚动进度进行。

  • Scroll Progress Timeline: 表示容器已滚动的距离,从0%到100%
  • View Progress Timeline: 标识容器内的元素相对于滚动距离的相对位置,从0%到100%。

本实践中使用的就是 View Progress Timeline,同时还使用到一个属性 animation-range

该属性定义了动画在时间轴上的附加范围的起始和结束位置,即动画将在时间轴的哪个位置开始和结束。它包含两个子属性,可以分别来设置动画的起始和结束位置:

  • animation-start:指定动画的起始位置,可以使用百分比、时间值或关键字来表示。
  • animation-end:指定动画的结束位置,可以使用百分比、时间值或关键字来表示。

2.2.Scroll Snapping

Scroll Snap 可以直译为“滚动捕捉技术”,它允许用户完成滚动之后将视口锁定到某个元素的位置。实现滚动捕捉主要依靠两个属性:

  • 父元素属性:scroll-snap-type 属性,scroll-snap-type: none | [ x | y | inline | block ] [ mandatory | proximity ]
  • 子元素属性:scroll-snap-align 属性,scroll-snap-align: [ none | start | end | center ]{1,2}

scroll-snap-type 属性定义在滚动容器中的一个临时点(snap point)如何被严格的执行。滚动容器的轴表示滚动方向,它可以是水平或垂直的,x值表示水平滚动,而y表示垂直滚动。

我们不仅可以定义 Scroll Snap 的方向,还可以定义它的严格程度,这可以通过使用 scroll-snap-type 值的 mandatory | proximity 来实现,mandatory 关键字意味着浏览器必须捕捉到每个滚动点,proximity 会吸附到定义的点。

scroll-snap-align 属性用来定义滚动元素如何紧贴边界,滚动容器的子元素需要一个对齐点,它们可以对齐到这个点。

2.3.object-view-box

object-view-box 属性在一个元素上指定了一个 "视图框",类似于 <svg viewBox> 属性,在元素的内容上进行缩放或平移。

2.4.clamp 函数

clamp() 函数的作用是把一个值限制在一个上限和下限之间,当这个值超过最小值和最大值的范围时,在最小值和最大值之间选择一个值使用。它接收三个参数:最小值、首选值、最大值。

2.5.伪元素::-webkit-scrollbar

::-webkit-scrollbar 是CSS伪元素,它会对设置了 overflow:scroll 样式的元素的滚动条样式产生影响。

注意:该特性是非标准的,请尽量不要在生产环境中使用它!

更多参考:https://developer.mozilla.org/zh-CN/docs/Web/CSS/::-webkit-scrollbar

猜你喜欢

3.实现方案

小懒首先通过 HTML Emmet 快速创建页面框架,然后开始对容器增加基础样式和现代 CSS 样式,最后实现滚动动画。

3.1.创建页面框架

使用 html:5div[class="gallery-wrapper"]>section[class="gallery"]>ul[class="gallery-list"]>(li[class="gallery-list-item"]>(figure>(img[src="./demo.jpeg"]+(figcaption>(span{0.5x}+span{text})))))*7 快速创建页面框架和 Gallery 容器。

3.2.增加 Base Styles

基础样式我们使用了现代 CSS的原生 CSS 嵌套(具体参加【插入链接),同时使用了 custom propertygridclamp()padding-inline 等现代 CSS 属性。

*,
*:after,
*:before {
box-sizing: border-box;
}

:root {
--image-size: clamp(200px, 30vw, 650px);
}
body {
margin: 0;
display: grid;
place-items: center;
min-height: 100vh;
background: #000;
overflow: hidden;
}
.gallery-wrapper {
position: relative;
.gallery {
overflow-x: scroll;
width: 100vw;
padding-inline: calc(50vw - (var(--image-size) * 0.5));
padding-block: 4lh;

&::-webkit-scrollbar {
height: 0;
opacity: 0;
}

.gallery-list {
display: flex;
width: fit-content;
padding: 0;
margin: 0;
list-style-type: none;
gap: 0.875rem;
.gallery-list-item {

& figure {
margin: 0;

& img {
width: var(--image-size);
object-fit: cover;
transform-origin: 0 50%;
}

& figcaption {
width: var(--image-size);
padding: 10px 0;
color: #fff;
font-size: 1.25rem;
text-align: center;

& span:last-of-type {
color: #999;
}
}
}
}
}
}
}

效果如下:

3.3.增加 Scroll Snapping

.gallery {
scroll-snap-type: x mandatory;

.gallery-list {
.gallery-list-item {
scroll-snap-align: center;
}
}
}

3.4.增加 object-view-box

给个图片增加一个视图框,以实现图片广角镜头、超广角镜头和长焦镜头效果。

.gallery {
.gallery-list {
.gallery-list-item {
& figure {
& img {
object-view-box: inset(
var(--crop, 0) var(--crop, 0) var(--crop, 0) var(--crop, 0)
);
}
}

&:nth-of-type(1) {
--crop: 40%;
}
&:nth-of-type(2) {
--crop: 0%;
}
&:nth-of-type(3) {
--crop: 10%;
}
&:nth-of-type(4) {
--crop: 16%;
}
&:nth-of-type(5) {
--crop: 20%;
}
&:nth-of-type(6) {
--crop: 24%;
}
&:nth-of-type(7) {
--crop: 30%;
}
}
}
}

3.4.增加 Scroll-driven Animations

此处用 @supports 判断浏览器是否支持 animation-timeline

.gallery {
.gallery-list {
.gallery-list-item {
view-timeline-name: --item;
view-timeline-axis: inline;
& figure {
& img {
opacity: var(--starting-opacity, 1);
scale: var(--starting-scale, 1);
translate: var(--starting-x, 0) 0;
}
}
}
}
}
@supports (animation-timeline: view()) {
img {
--starting-scale: 0.65;
--starting-opacity: 0.3;
--starting-x: -36%;
animation: highlight both linear;
animation-timeline: view(inline);
animation-range: cover 0% cover 50%;
}
@keyframes highlight {
50% {
translate: 0 0;
scale: var(--starting-scale);
opacity: var(--starting-opacity);
}
to {
translate: 0 0;
scale: 1;
opacity: 1;
}
}
figcaption {
position: absolute;
left: 50%;
bottom: 0;
translate: -50% 0;
opacity: 0;
animation: show both linear;
animation-timeline: --item;
}
@keyframes show {
0%,
45%,
55%,
100% {
opacity: 0;
}
50% {
opacity: 1;
}
}
}

4.总结

现代 CSS 的特性是不是很酷😎,本文中还使用到了 padding-inlinepadding-blocklh unit 等现代 CSS 特性,如果你也对现代 CSS 感兴趣,欢迎关注小懒,小懒也在努力学习中哦😯。

大家都在看

关注下方公众号,加群福利多多
继续滑动看下一个

现代CSS:纯 CSS 实现苹果风格(Apple-style)的图片滚动器

小懒 FED实验室
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存