了解打造 Designcember 节日日历式体验所用的过程和工具。
12 月是一年中的最后一个月,人们会使用各种日历来倒计时和庆祝,因此我们想重点介绍社区和 Chrome 团队的网络内容。我们每天都会重点介绍一项与界面开发和设计相关的内容,共发布了 31 项精选内容,其中包括 26 个新的演示网站、工具、通告、播客、视频、文章和案例研究。
如需查看完整体验,请访问 designcember.com。
概览
我们的目标是尽可能以最少的字节提供易于访问、奇思妙想、现代且响应迅速的 Web 体验。我们希望重点介绍容器查询等新的响应式 API,并在以设计为中心且资源丰富的网站中添加一个漂亮的深色模式示例。为此,我们压缩了文件、提供了多种格式、使用了针对静态网站生成进行了优化的构建工具、发布了新的 polyfill 等。
从随心开始
Designcember 日历网站的设计理念是,一方面展示我们希望在整个 12 月期间重点推介的所有工作,另一方面本身也充当一个演示网站。我们决定建造一栋可响应环境变化的公寓楼,它可以变得更高更窄,也可以变得更矮更宽,窗户会在框架内自行重新排列。每个时间段代表一天(即一段内容)。 我们与插画家 Alice Lee 合作,将我们的愿景变为现实。
Alice 分享了一些启发性的内容,即使是早期概念,也令人兴奋。她负责美术设计,我们负责架构开发。早期讨论围绕宏观布局、建筑物及其窗户展开。随着视口可用空间的增加,窗口会如何调整为显示一列、两列或三列?它们能收缩或延伸多远?建筑物最大尺寸是多少?窗口会偏移多少?
以下是使用 grid-auto-flow: dense
的自适应原型预览,展示了网格算法如何自动放置窗口。我们很快意识到,虽然宽高比网格在展示海报图片方面效果出色,但无法让窗口在非均匀的可用空间中放大和缩小,也无法展示容器查询的强大功能。
当一般网格相对稳定且能体现出建筑物及其窗户的响应度方向感后,我们就可以专注于单个窗口。与网格中的其他窗口相比,某些窗口会更频繁地伸展、缩小、挤压、放大和重新组合。
每个窗口都需要处理一定程度的大小调整湍流。以下是窗口的原型,演示了其对颠簸的响应能力,展示了我们预计每个交互式窗口的调整幅度。
使用精灵集的窗口动画
某些窗口会显示动画,以增强互动体验。动画是在 Photoshop 中逐帧手绘的。系统会导出每帧,使用此精灵贴片生成器将其转换为精灵贴片,然后使用 Squoosh 进行优化。然后,CSS 动画会使用 background-position-x
和 animation-timing-function
,如以下示例所示。
.una
background: url("/day1/una_sprite.webp") 0% 0%;
background-size: 400% auto;
}
.day:is(:hover, :focus-within) .una {
animation: una-wave .5s steps(1) alternate infinite;
}
@keyframes una-wave {
0% { background-position-x: 0%; }
25% { background-position-x: 300%; }
50% { background-position-x: 200%; }
75% { background-position-x: 100%; }
}
某些动画(例如第 6 天的存钱罐)是基于步骤的 CSS 动画。
我们使用 steps()
采用了类似的技术来实现此效果,不同之处在于关键帧是 CSS 转换位置,而不是背景位置。
CSS 遮罩
有些窗户的形状独特。我们使用了遮罩和 aspect-ratio
来创建可伸缩、形状独特且自适应的窗口。
如需创建遮罩(例如适用于 Windows 8 的遮罩),需要掌握一些传统的 Photoshop 技能,以及对 Web 上的遮罩工作原理有一点了解。我们来看看第 8 天的时段。
为了将内部四叶草形状转换为蒙版,必须将其作为单独的形状分离出来,并填充白色。白色会告知 CSS 哪些内容会保留,而白色区域之外的所有内容都不会保留。在 Photoshop 中,选择窗口内部,羽化 1 像素(以消除锯齿化问题),然后填充白色,并以与窗口框架相同的高度和宽度导出。这样,框架和遮罩就可以直接叠加在一起,以便按预期在框架内显示内部内容。
完成后,您可以修改窗口的内容,并且这些内容始终会显示在自定义框架内。下图显示了窗口的深色模式版本,其中使用了不同的背景渐变和对灯光应用了 CSS 光晕滤镜。
遮盖功能还支持基于容器查询的自适应窗口。在第九个窗口中,有一个角色隐藏在遮罩后面,直到窗口变窄。为了确保用户无法调整图片超出框架,Alice 为我们完成了完整的角色。角色在窗口中被遮罩,但植物没有,因此我们遇到的另一个挑战是将遮罩的元素与未遮罩的层叠加,并确保它们一起良好缩放。
下图展示了未在窗口和角色上应用遮罩时的效果。
压缩图片
为了保持插图的保真度,并确保高清屏幕不会给用户带来模糊的体验,Alice 采用了 3x 像素比率。原计划是使用 imgix 并在其服务器上提供经过优化的图片和格式,但我们发现,使用 Squoosh 工具手动调整可以将流量节省 50% 或更多。
在压缩方面,插图存在独特的挑战,尤其是 Alice 使用的笔触和透明粗糙边缘样式。我们选择使用 Squoosh 将 Photoshop 导出的每张 3x png 图片压缩为较小的 png、webp 和 avif 图片。每种文件类型都有自己的特殊压缩功能,我们压缩了 50 多张图片,才找到了一些常见的优化设置。
由于需要优化 200 多张图片,Squoosh CLI 至关重要,如果手动完成所有这些操作,可能需要数天时间。确定常见优化设置后,我们将其作为命令行指令提供,并将整个 PNG 图片文件夹批量处理为 WebP 和 AVIF 压缩图片。
以下是使用的 AVIF CLI squoosh 命令示例:
npx @squoosh/cli --quant '{"enabled":true,"zx":0,"maxNumColors":256,"dither":1}' --avif '{"cqLevel":19,"cqAlphaLevel":17,"subsample":1,"tileColsLog2":0,"tileRowsLog2":0,"speed":6,"chromaDeltaQ":false,"sharpness":5,"denoiseLevel":0,"tune":0}' image-1.png image-2.png image-3.png
将优化后的海报图片签入到代码库后,我们就可以开始从 HTML 加载它们了:
<picture>
<source srcset="/day1/inner-frame.avif" type="image/avif">
<source srcset="/day1/inner-frame.webp" type="image/webp">
<img alt="" decoding="async" role="presentation" src="/day1/inner-frame.png">
</picture>
编写图片源代码很重复,因此我们创建了一个 Astro 组件,只需一行代码即可嵌入图片。
<Pic filename="day1/inner-frame" role="presentation" />
使用屏幕阅读器和键盘的用户
Designcember 的大部分体验都是通过艺术和互动窗口获得的。我们非常重视键盘用户能够使用该网站并查看窗口,以及屏幕阅读器用户能够获得良好的旁白体验。
例如,在嵌入图片时,我们使用 role="presentation"
将图片标记为适合屏幕阅读器的呈现图片。我们认为,如果 alt
说明有 5 到 12 个断点,用户体验会很差。因此,我们将图片标记为演示图片,并提供了整体窗口旁白。这样一来,用户在屏幕阅读器上浏览窗口时,就会有一种很好的叙事感,我们希望这有助于传达该网站想要分享的奇思妙想和乐趣。
以下视频展示了键盘体验的演示。Tab、Enter、空格键和 Esc 键均用于在窗口弹出式窗口和窗口之间协调焦点。
屏幕阅读器体验具有特殊的 ARIA 属性,可让内容更加清晰。例如,日期链接只会显示“1”或“2”,但添加了一些 ARIA 后,系统会读出“第一天”和“第二天”。此外,所有图片都会汇总到一个标签中,因此每个窗口都有一个说明。
Astro,以静态为主、以组件为驱动的网站生成器
Astro 让团队能够轻松地在网站上协同工作。组件模型对 Angular 和 React 开发者来说都很熟悉,而作用域限定的类名称样式系统有助于每位开发者了解自己在窗口上的工作不会与其他人的冲突。
天(作为组件)
每天都是一个组件,用于从构建时数据存储区提取状态。这样,我们就可以在 HTML 到达浏览器之前运行模板逻辑。该逻辑会确定相应日期是否应显示其提示,因为非活动日期不会显示弹出式窗口。
构建会每小时运行一次,并且构建时间数据存储区会在构建服务器午夜过后解锁新的一天。这些自更新且自给自足的小系统可确保网站保持最新状态。
作用域样式和公开属性
Astro 会将在其组件模型中编写的样式进行范围限定,这让工作负载更容易分配给许多团队成员,同时也让使用 Open Props 变得有趣。Open Props normalize.css 样式非常适合自适应(浅色和深色)主题,还能帮助整理段落和标题等内容。
作为 Astro 的早期采用者,我们在使用 PostCSS 时遇到了一些问题。例如,由于构建问题过多,我们无法更新到最新的 Astro 版本。您可以花更多时间优化构建和开发者工作流。
灵活的容器
有些窗口会放大和缩小,以保持宽高比,以便保留其图形。我们使用了一些其他窗口来展示基于组件的架构与容器查询的强大功能。容器查询意味着窗口可以拥有自己的自适应样式信息,并根据自己的大小进行重新调整。有些窗口从窄变宽,因此需要调整其中媒体的大小和位置。
随着窗口可用空间的增加,我们可以调整窗口的大小或子元素以适应。事实证明,为了实现自适应窗口,容器查询不仅仅是展示的乐趣,而是必不可少的,并且大大简化了编排特定布局的流程。
.day {
container: inline-size;
}
.day > .pane {
min-block-size: 250px;
@container (min-width: 220px) {
min-block-size: 300px;
}
@container (min-width: 260px) {
min-block-size: 310px;
}
@container (min-width: 360px) {
min-block-size: 450px;
}
}
此方法不同于保持宽高比。这可提供更大的可控性和更多机会。在达到一定大小后,许多儿童都会移动位置以适应新的布局。
容器查询还支持块方向(垂直)容纳,因此随着窗口长度的增加,我们可以调整其样式以适应相应大小。这在基于高度的查询(我们单独使用)以及基于宽度的查询中有所体现:
.person {
place-self: flex-end;
margin-block: 25% 50%;
margin-inline-start: -15%;
z-index: var(--layer-1);
@container (max-height: 350px) and (max-width: 425px) {
place-self: center flex-end;
inline-size: 50%;
inset-block-end: -15%;
margin-block-start: -2%;
margin-block-end: -25%;
z-index: var(--layer-2);
}
}
我们还使用了容器查询来显示和隐藏细节,因为在尺寸较小时,图片会变得越来越拥挤,而在尺寸较大时,图片会变得越来越空旷。窗口 9 就是一个很好的示例:
跨浏览器支持
为了打造出色的现代跨浏览器体验,尤其是对于容器查询等实验性 API,我们需要一个出色的 polyfill。我们向团队发出了号召,Surma 牵头构建了一个新的容器查询 polyfill。该 polyfill 依赖于 ResizeObserver、MutationObserver 和 CSS :is() 函数。因此,所有现代浏览器都支持该 polyfill,具体而言,Chrome 和 Edge 从 88 版开始、Firefox 从 78 版开始、Safari 从 14 版开始支持。使用此 polyfill 时,允许使用以下任一语法:
/* These are all equivalent */
@container (min-width: 200px) {
/* ... */
}
@container (width >= 200px) {
/* ... */
}
@container size(width >= 200px) {
/* ... */
}
深色模式
最后一个对 Designcember 网站至关重要的细节是采用美观的深色主题。我们希望展示如何利用艺术本身,成为打造出色深色模式体验的积极参与者。为此,我们以编程方式调整了每个窗口本身的背景样式,并在制作窗口海报图片时尽可能使用 CSS。大多数背景都是 CSS 渐变,这样更容易调整其颜色值。然后,我们将海报图片叠加在这些元素上。
其他彩蛋
个性化设置
我们在该页面中添加了一些个性化元素,使网站更具特色。第一个是角色,我们团队从中汲取了灵感。我们还在非活跃日添加了复古风格光标,并对 favicon 样式进行了一些调整。
实用功能
其他一些额外的功能细节包括“跳转到今天”功能,以及坐在建筑物顶部的鸟。点击或按下 Enter 键即可跳转到页面上的当天,以便快速查看最新发布的内容。
Designcember.com 还有一个特殊的打印样式表,我们会提供最适合 8.5 x 11 英寸纸张的特定图片,以便您自行打印日历,让节日气氛全年洋溢。
总而言之,我们付出了大量努力,打造了有趣、奇妙的现代 Web 体验,以庆祝 12 月整个月的界面开发活动。希望您喜欢!