了解打造 Designcember 节日日历式体验所用的过程和工具。
鉴于十二月精神和人们用来倒计时和庆祝的众多日历,我们想要重点推介来自 Chrome 社区和 Chrome 团队的网络内容。每天,我们都会重点介绍一个与界面开发和设计相关的内容,共计 31 个亮点,其中包括 26 个新的演示网站、工具、公告、播客、视频、文章和案例研究。
如需查看完整体验,请访问 designcember.com。
概览
我们的目标是以尽可能少的字节提供易用、新奇、现代且响应迅速的网络体验。我们希望重点介绍容器查询等新的自适应 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
来创建可伸缩、形状独特且自适应的窗口。
要创建蒙版(例如为窗口 8 创建的蒙版),您需要掌握一些经典的 Photoshop 技能,以及有关蒙版如何在网络上工作的一些知识。我们来看看第八天的回溯期。
为了将内部四叶草形状转换为蒙版,必须将其作为单独的形状分离出来,并填充白色。白色告知 CSS 哪些内容会保留,白色之外的其他内容不会保留。在 Photoshop 中,窗口内部被选中,以羽化 1px(以消除混叠问题)为中心,然后填充白色,并以与窗口框架相同的高度和宽度导出。这样一来,框架和蒙版便可以直接相互层叠,从而按预期显示框架内的内部内容。
完成后,您可以修改窗口的内容,并且这些内容始终会显示在自定义框架内。以下图片显示了深色模式下的窗口,其中应用了不同的背景渐变和对灯光应用了 CSS 光晕滤镜。
遮盖功能还支持基于容器查询的响应式窗口。在第九个窗口中,有一个角色隐藏在遮罩后面,直到窗口变窄。为了确保用户无法将图片调整到画面外,Alice 为我们完成了完整的角色。角色在窗口中被遮罩,但植物没有,因此我们遇到的另一个挑战是将遮罩的元素与未遮罩的层叠加,并确保它们一起良好缩放。
下图展示了未在窗口和角色上应用遮罩时的效果。
压缩图片
为了保持插图的保真度,并确保高清屏幕不会给用户带来模糊的体验,Alice 采用了 3x 像素比率。原计划是使用 imgix 并在其服务器上提供经过优化的图片和格式,但我们发现,使用 Squoosh 工具手动调整可以将流量节省 50% 或更多。
在压缩方面,插图存在独特的挑战,尤其是 Alice 使用的笔触和透明粗糙边缘样式。我们选择 Squoosh 将每个 3x Photoshop 导出的 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 渐变,这样更容易调整其颜色值。然后,我们在这些基础上叠加了艺术作品。
其他彩蛋
个性化设置
我们在页面中添加了一些个性化元素,使网站更具特色。第一个是角色阵容,灵感来自我们的团队。我们还为非活动状态添加了一个怀旧风格的光标,并尝试使用网站图标样式。
实用功能
其他一些额外的功能细节包括“跳转到今天”功能,以及坐在建筑物顶部的鸟。点击或按下 Enter 键即可跳转到页面上的当天,以便快速查看最新发布的内容。
Designcember.com 还有一个特殊的打印样式表,我们会提供最适合 8.5 x 11 英寸纸张的特定图片,以便您自行打印日历,让节日气氛全年洋溢。
总而言之,在 12 月份,我们投入了大量精力来打造新颖有趣的现代 Web 体验,以庆祝整个界面开发。希望您喜欢!