构建“短片故事”组件

简要介绍如何在网上打造类似于 Instagram 快拍的体验。

在这篇博文中,我想分享一下如何针对 它不仅响应迅速、支持键盘导航, 。

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
演示

如果您更喜欢亲自构建此故事组件的实操演示, 请查看“故事”组件 Codelab

如果你更喜欢视频,可以参阅此博文的 YouTube 版本:

概览

短片故事用户体验的两个热门示例是 Snapchat 故事和 Instagram 短片故事(更不用说舰队了)。 从一般用户体验术语来看,故事通常是一种仅适用于移动设备、以点按为中心的导航模式 多项订阅例如,在 Instagram 上,用户会打开朋友的故事 并浏览其中的图片他们一般会和很多朋友一起 。通过点按设备的右侧,用户会跳至该好友的 下一篇报道。通过向右滑动,用户可以跳至另一个好友。 故事组件与轮播界面非常相似,但 与单维数组相反。就好像里面有个轮播界面 每个轮播界面🤯

<ph type="x-smartling-placeholder">
</ph> 使用卡片直观呈现的多维数组。从左到右是一叠紫色边框卡片,每张卡片中都有 1 张蓝绿色边框的卡片。列表形式的列表。 <ph type="x-smartling-placeholder">
</ph> 第 1 个好友轮播界面
第 2 个“堆叠”故事轮播界面
👍? 以列表形式列出,也称为多维数组

为工作选择合适的工具

总而言之,我发现这个组件的构建非常简单,这要归功于 关键网络平台功能下面我们来逐一介绍!

CSS 网格

事实证明,我们的布局对 CSS Grid 来说并不繁琐,因为它配备了一些 来整理内容的有效方式

“好友”布局

我们的主要 .stories 组件封装容器是移动设备优先的水平滚动视图:

.stories {
  inline-size: 100vw;
  block-size: 100vh;

  display: grid;
  grid: 1fr / auto-flow 100%;
  gap: 1ch;

  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  touch-action: pan-x;
}

/* desktop constraint */
@media (hover: hover) and (min-width: 480px) {
  max-inline-size: 480px;
  max-block-size: 848px;
}
使用 Chrome 开发者工具” 设备模式 突出显示由 Grid 创建的列

我们来细分一下 grid 布局:

  • 我们在移动设备上使用 100vh100vw 明确填充视口,并在桌面设备上限制尺寸
  • / 用于分隔行模板和列模板
  • auto-flow”可以翻译成grid-auto-flow: column
  • 自动流模板为 100%,在本例中为滚动窗口宽度

在手机上,可以将行大小视为视口高度, 每列代表视口宽度接着来谈谈 Snapchat 故事 Instagram 快拍的例子,每一列都是一位朋友的故事。我们希望朋友 所以我们有可以滚动到的位置。 网格将创建所需的列(无论其需要多少列),才能为每个好友布局您的 HTML 为我们创建一个动态的自适应滚动容器。网格 使我们能够将整个效果集中起来。

堆叠

对于每个朋友,我们都需要将他们的故事置于可随时分页的状态。 为准备动画和其他有趣的模式,我选择了堆栈。 我说“堆叠”的意思是 三明治,这不像是从侧面看的。

借助 CSS 网格,我们可以定义一个单单元格网格(即正方形),其中行 和列共用一个别名 ([story]),然后每个子项都会分配到该别名 带别名的单单元格空格:

.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
.story {
  grid-area: story;
  background-size: cover;
  
}

这样,我们的 HTML 便可控制叠放顺序,同时保留了所有元素 请注意,我们无需对 absolute 定位或 z-index 执行任何操作, 我们不需要使用 height: 100%width: 100% 进行方框正确。父级网格 已经定义了故事图片视口的大小,因此这些故事组件都没有 需要告诉他们来填充!

CSS 滚动贴靠点

“CSS 滚动贴靠点”规范 只需在滚动时将元素锁定到视口内即可在这些 CSS 属性存在之前 不得不用到 JavaScript,而且至少要这样操作很棘手。结账 CSS 滚动贴靠点简介

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">
不使用和使用 scroll-snap-points 样式的水平滚动。 如果不设置,用户可以照常自由滚动。将浏览器轻柔地放在每个项上。
父级
.stories {
  display: grid;
  grid: 1fr / auto-flow 100%;
  gap: 1ch;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  overscroll-behavior: contain;
  touch-action: pan-x;
}
具有滚动的父级定义了贴靠行为。
儿童
.user {
  display: grid;
  grid: [story] 1fr / [story] 1fr;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}
儿童选择成为 Snap 目标。

我选择“滚动快照点”有几个原因:

  • 免费无障碍功能。“滚动贴靠点”规范规定,如果按下 向左箭头向右箭头键应在相应贴靠点之间移动 默认情况。
  • 日益增多的规范。“滚动贴靠点”规范将获得新功能和改进 这意味着我的故事组件很可能只有在 继续介绍吧
  • 易于实施。滚动贴靠点实际上是专为 以触摸为中心的水平分页用例。
  • 自由的平台式惯性。每个平台都会按照其样式进行滚动和停放, 标准化的惯性,可能具有不可思议的滚动和静止风格。

跨浏览器兼容性

我们在 Opera、Firefox、Safari 和 Chrome 以及 Android 和 iOS 上进行了测试。以下是 简要概述我们在功能和支持方面存在哪些差异的网络功能。

我们确实有一些 CSS 不适用,因此一些平台目前错失了用户体验 优化。我不喜欢无需管理这些功能,而且有信心 最终到达其他浏览器和平台

scroll-snap-stop

轮播是促使 Google 开发 CSS 滚动贴靠点规范。与短片故事不同,轮播界面不一定总是需要停下来 对每张图片执行的操作这种做法可能没有问题, 用户可在轮播界面中快速循环展示另一方面,最好是逐个浏览各个故事 而这正是 scroll-snap-stop 提供的功能。

.user {
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

在撰写这篇博文时,只有基于 Chromium 的平台支持 scroll-snap-stop 。结账 浏览器兼容性 获取更新。但它不是障碍。这只是表示 用户可能会意外跳过好友因此,用户必须格外小心, 我们需要编写 JavaScript,以确保跳过的朋友不会标记为已查看。

有关详情,请参阅 规范

overscroll-behavior

您是否遇到过以下情况:滚动浏览模态窗口时突然 要开始滚动模态窗口后的内容吗? overscroll-behavior 让开发者陷入滚动操作,绝不让它 离开。它适合各种场合。“我的故事”组件会用到它 以防止其他滑动和滚动手势离开 组件。

.stories {
  overflow-x: auto;
  overscroll-behavior: contain;
}

Safari 和 Opera 是两种 支持这一点 完全没问题。这些用户将获得与以往一样的滚动体验 可能永远都不会注意到此增强功能。我本人就非常狂热 将它纳入我实现的几乎所有滚动回弹功能中这是一个 添加的内容无害,但只会改善用户体验。

scrollIntoView({behavior: 'smooth'})

当用户点按或点击并阅读完朋友的故事集后, 这时就可以移动到滚动贴靠点集中的下一个朋友了。包含 JavaScript 后,我们就可以引用下一位朋友并请求 滚动进入视图。对于这方面的基础知识,相关支持非常有效:每个浏览器 并将其滚动到了用户视野范围内但并不是所有浏览器都'smooth'。这只是表示 而是会滚动到用户视野范围内,而不是被贴靠。

element.scrollIntoView({
  behavior: 'smooth'
})

Safari 是唯一不支持此处 behavior: 'smooth' 的浏览器。结账 浏览器兼容性 获取更新。

实践活动

现在你知道我怎么做到的了,你会怎么做?!让我们实现 方法,并学习在 Web 上构建应用的所有方式。创建 Glitch 把你的版本发到 Twitter 上,我会将其添加到 下方的社区混剪部分。

社区混剪作品