使用 CSS 动画滑动图片以显示文本

Avatar of Jesper Ekstrom
Jesper Ekstrom

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

我想更仔细地研究一下 CSS animation 属性,并逐步演示一下我在自己 作品集网站 上使用的一种效果:使文本从移动对象的后面出现。如果您想查看最终产品,这里有一个 独立示例

以下是我们将要使用的内容

查看 CodePen 上的笔
显示文本动画第 4 部分 – 响应式
,作者:Jesper Ekstrom (@jesper-ekstrom)
CodePen 上。

即使您对这种效果本身并不感兴趣,这将是一个极好的练习,可以扩展您的 CSS 知识并开始创建您自己的独特动画。就我而言,深入研究动画帮助我增强了对 CSS 能力的信心,并提高了我的创造力,这让我对前端开发整体产生了更大的兴趣。

准备好了吗?开始吧!

步骤 1:标记主要元素

在开始动画之前,让我们创建一个覆盖整个视口的父容器。在其中,我们将添加文本和图像,每个都放在一个单独的 div 中,以便稍后更容易自定义它们。HTML 标记将如下所示

<!-- The parent container -->
<div class="container"> 
  <!-- The div containing the image -->
  <div class="image-container">
  <img src="https://jesperekstrom.com/wp-content/uploads/2018/11/Wordpress-folder-purple.png" alt="wordpress-folder-icon">
  </div>
  <!-- The div containing the text that's revealed -->
  <div class="text-container">
    <h1>Animation</h1>
  </div>
</div>

我们将使用这个可靠的 转换技巧 使 div 垂直和水平居中,并在父容器中使用 position: absolute;,并且由于我们希望图像显示在文本前面,因此我们将更高的 z-index 值添加到它。

/* The parent container taking up the full viewport */
.container {
  width: 100%;
  height: 100vh;
  display: block;
  position: relative;
  overflow: hidden;
}

/* The div that contains the image  */
/* Centering trick: https://css-tricks.cn/centering-percentage-widthheight-elements/ */
.image-container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
  z-index: 2; /* Makes sure this is on top */
}

/* The image inside the first div */
.image-container img {
  -webkit-filter: drop-shadow(-4px 5px 5px rgba(0,0,0,0.6));
  filter: drop-shadow(-4px 5px 5px rgba(0,0,0,0.6));
  height: 200px;
}

/* The div that holds the text that will be revealed */
/* Same centering trick */
.text-container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
  z-index: 1; /* Places this below the image container */
  margin-left: -100px;
}

在本文的代码示例中,我们省略了供应商前缀,但在生产环境中使用时,绝对应该考虑它们。

到目前为止,这给了我们什么,这基本上是我们的两个元素一个叠加在另一个之上。

查看 CodePen 上的笔
显示文本动画第 1 部分 – 邮件元素
,作者:Jesper Ekstrom (@jesper-ekstrom)
CodePen 上。

步骤 2:隐藏文本后面的块

为了使我们的文本从左到右开始显示,我们需要在 .text-container 内添加另一个 div

<!-- ... -->

  <!-- The div containing the text that's revealed -->
  <div class="text-container">
    <h1>Animation</h1>
    <div class="fading-effect"></div>
  </div>
  
<!-- ... -->

…并向其添加这些 CSS 属性和值

.fading-effect {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 100%;
  background: white;
}

如您所见,文本现在隐藏在此块后面,该块具有白色背景颜色以与我们的父容器混合。

如果我们尝试更改块的宽度,文本将开始出现。继续在 Pen 中尝试使用它

查看 CodePen 上的笔
显示文本动画第 2 部分 – 隐藏块
,作者:Jesper Ekstrom (@jesper-ekstrom)
CodePen 上。

还有另一种方法可以在不添加额外的带背景的块的情况下实现此效果。我将在文章后面介绍该方法。🙂

步骤 3:定义动画关键帧

我们现在准备好了有趣的部分!要开始为我们的对象设置动画,我们将使用 animation 属性 及其 @keyframes 函数。让我们首先创建两个不同的 @keyframes,一个用于图像,一个用于文本,最终它们将如下所示

/* Slides the image from left (-250px) to right (150px) */
@keyframes image-slide {
  0% { transform: translateX(-250px) scale(0); }
  60% { transform: translateX(-250px) scale(1); }
  90% { transform: translateX(150px) scale(1); }
  100% { transform: translateX(150px) scale(1); }  
}

/* Slides the text by shrinking the width of the object from full (100%) to nada (0%) */
@keyframes text-slide {
  0% { width: 100%; }
  60% { width: 100%; }
  75%{ width: 0; }
  100% { width: 0; }
}

我更喜欢将所有 @keyframes 添加到 CSS 文件的顶部,以获得更好的文件结构,但这只是一个偏好。

@keyframes 仅使用其百分比值的一小部分(主要来自 60-100%)的原因是我选择在相同的持续时间内为两个对象设置动画,而不是向应用它的类添加 animation-delay。那只是我的偏好。如果您选择这样做,请记住始终为 0% 和 100% 设置一个值;否则动画可能会开始反向循环或出现其他奇怪的交互。

要将 @keyframes 启用到我们的类,我们将在 CSS 属性 animation 上调用动画名称。例如,将 image-slide 动画添加到图像元素,我们将执行以下操作

.image-container img {
  /* [animation name] [animation duration] [animation transition function] */
  animation: image-slide 4s cubic-bezier(.5,.5,0,1);
}

@keyframes 的名称与创建类的工作方式相同。换句话说,只要在应用它的元素上调用相同的名称,名称实际上并不重要。

如果该 cubic-bezier 部分导致令人费解,请查看 Michelle Barker 的这篇文章。她深入探讨了该主题。但是,就本演示的目的而言,可以认为它是一种为对象从开始到结束的移动方式创建自定义动画曲线的方法。该网站 cubic-bezier.com 是一个在没有所有猜测的情况下生成这些值的好地方。

我们谈到了想要避免循环动画。我们可以使用 animation-fill-mode 子属性强制对象在动画达到 100% 后保持不动

.image-container img {
  animation: image-slide 4s cubic-bezier(.5,.5,0,1);
  animation-fill-mode: forwards;
}

到目前为止,一切顺利!

查看 CodePen 上的笔
显示文本动画第 3 部分 – @keyframes
,作者:Jesper Ekstrom (@jesper-ekstrom)
CodePen 上。

步骤 4:编写响应式代码

由于动画基于固定(像素)大小,因此播放视口宽度会导致元素移位,当我们尝试根据元素位置隐藏和显示元素时,这是一件坏事。我们可以创建多个动画在不同的媒体查询中处理它(这正是我最初所做的),但同时管理多个动画并不好玩。相反,我们可以使用相同的动画并在特定的断点处更改其属性。

例如

@keyframes image-slide {
  0% { transform: translatex(-250px) scale(0); }
  60% { transform: translatex(-250px) scale(1); }
  90% { transform: translatex(150px) scale(1); }
  100% { transform: translatex(150px) scale(1); }
}

/* Changes animation values for viewports up to 1000px wide */
@media screen and (max-width: 1000px) {
  @keyframes image-slide {
    0% { transform: translatex(-150px) scale(0); }
    60% { transform: translatex(-150px) scale(1); }
    90% { transform: translatex(120px) scale(1); }
    100% { transform: translatex(120px) scale(1); }
  }
}

我们到了,全部响应式!

查看 CodePen 上的笔
显示文本动画第 4 部分 – 响应式
,作者:Jesper Ekstrom (@jesper-ekstrom)
CodePen 上。

替代方法:无需彩色背景的文本动画

我之前承诺过我会展示一种不同的淡入淡出效果方法,所以让我们来谈谈它。

与其创建一个全新的 div — <div class="fading-effect"> — 我们可以使用一些颜色技巧来剪切文本并将其与背景混合

.text-container {
  background: black;
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

这使文本透明,从而允许其后面的背景颜色渗入并有效地隐藏它。而且,由于这是一个背景,我们可以更改背景宽度并查看文本如何被给定的宽度切割。这也使得能够向文本添加线性渐变颜色,甚至在其中显示背景图像。

我之所以没有在演示中选择这种方法,是因为它与 Internet Explorer 不兼容(请注意那些 -webkit 供应商前缀)。我们在实际演示中介绍的方法可以将文本替换为另一个图像或任何其他对象。


非常简洁的小动画,对吧?它相对微妙,并且可以作为 UI 元素的良好增强。例如,我可以看到它用于显示解释性文本甚至照片标题。或者,可以使用一些 JavaScript 在点击或滚动位置触发动画,使内容更具互动性。

对任何工作原理有任何疑问吗?看到可以改进的地方吗?请在评论中告诉我!