如何在 CSS 中重现一个漂亮的 Netflix 动画

Avatar of Chris Geelhoed
Chris Geelhoed

DigitalOcean 为您的旅程的每个阶段提供云产品。立即开始使用 200 美元的免费信用额度!

Netflix 浏览页面的设计在过去几年中一直保持着相似性。一个主要的组件是预览滑块,它允许用户滚动浏览内容并悬停在项目上以查看预览。

UI 的一个独特特点是其悬停行为。当节目预览在悬停时展开时,它旁边的卡片会向外推,这样它们就不会重叠。

就像这样

就像比尔·默瑞和布拉德·皮特在争夺聚光灯。

我们可以用 CSS 来实现!不需要 JavaScript。没有依赖项。纯 CSS。但在深入任何代码之前,以下是我们想要做的事情

  1. 悬停的卡片应该展开,同时保持其纵横比。
  2. 当卡片悬停时,其他卡片不应该改变大小,并且向外移动,以避免彼此重叠。
  3. 所有卡片应该彼此垂直居中。

听起来不错?现在让我们进入代码。

HTML 和弹性元素

让我们设置一行图像,代表 Netflix 的视频预览。这包括

  • 一个  .container 父元素,其中包含多个 .item 元素
  • 每个 .item 元素包含一个包裹在锚标签中的图像
  • .container 变成一个 flex 容器,将项目水平对齐
  • .item 类设置 flex 行为,以便它们在行中占用相等的空间

悬停时展开项目

我们的下一步是让项目在悬停时展开。我们可以通过为元素的 width 设置动画来实现,但这会影响文档的流,并导致悬停项目的兄弟节点收缩 - 此外,为 width 属性设置动画在某些情况下会导致 性能下降

为了避免挤压悬停项目的兄弟节点,我们将为 transform 属性(具体来说是它的 scale() 函数)设置动画,而不是 width。这不会像 width 那样影响文档流。

将兄弟节点向外移动

让悬停项目的兄弟节点远离悬停项目是整个过程中最棘手的部分。我们可以使用的一个 CSS 功能是 通用兄弟节点组合器。这让我们可以选择所有位于悬停项目之后的兄弟节点。

我们将转向 transform 属性的 translateX() 函数来移动事物。同样,为 transform 设置动画比其他影响文档流的属性(如边距和填充)要好得多。

由于我们已将项目在悬停时设置为放大 150%,因此平移应该设置为 25%。这是悬停项目占用额外空间的一半。

.item:hover ~ .item {
  transform: translateX(25%);
}

这处理了向右移动,但我们如何平移左侧的项目?由于通用兄弟节点组合器仅适用于位于给定选择器之后的兄弟节点(不能“向后”),因此我们需要另一种方法。

一种方法是在父容器本身添加一个额外的悬停规则。以下是计划

  • 当悬停父容器时,将容器内的所有项目向左移动。
  • 使用通用兄弟节点组合器使位于悬停项目之后的项目向右移动。
  • 变得超级具体,这样悬停的项目就不会像其他项目一样被平移。

我们假设您的文档使用的是从左到右的书写模式。如果您想在从右到左的上下文中使用此效果,您需要将悬停的外部容器内的所有项目都向移动,并使用通用兄弟节点组合器将所有选定的项目向移动。

演示时间!

还有一点需要注意:此最终版本使用 :focus:focus-within 伪类来支持键盘导航。Netflix 示例没有使用它,但我认为这对无障碍性来说是一个不错的补充。


就是这样!是的,我们可以使用 JavaScript 事件监听器而不是 CSS 悬停规则,这可能更有利于维护和可读性。但有时看到 CSS 能做到什么程度很有趣!