图片与标题的 Ken Burns 动效

原文地址: 《Animated Image Gallery Captions with Bonus Ken Burns Effect"》
我从事前端开发13年有余,一直致力于研究现代CSS解决方案,这是我该系列文章的第6篇
本文主要讨论:
object-fit用于响应式图像缩放CSS Grid"hack" 升级position absolute方式CSS transforms动画效果
如果你曾经使用jQuery和position: absolute来解决图像标题文字动画的问题,或者通过处理元素的宽高动画来实现,如果你想在响应式的图片上实现,这次的升级非常适合你。
有关object-fit的介绍请看这篇文章(系列02):
https://dev.to/5t3ph/css-only-full-width-responsive-images-2-ways-2njm
基础HTML
下面是我们基础的HTML,它是一个ul,其中每个li"card"包含了图片和标题。
以上是原作者的代码,笔者建议图片使用
<figure>和<figcaption>标签 可附标题内容元素
我使用不同大小的图片,既是为了展示object-fit如何适配它的容器,也是为了减少picsum服务中重复图片。
基础样式
由于我们使用了列表样式,所以我们需要删除默认的列表样式,同时我们还要将列表设置为grid容器。
这样初始的样式就完成了,首先将我们的列表项放在一行中,先不设置图片的样式

card 和 Image 样式
如果你和我一样,并且在过去几年中尝试过这样做,你可能会把鼠标滚过房间,试图找出为什么position:absolute不能很好地处理jQuery动画。
CSS Grid和CSS transforms在这里来拯救你了! 🎉
我们将card设置grid样式,并设置一个高度。而我们仍然会使用overflow: hidden, 来确保标题最初隐藏image内容中。
接下来,我们在image上设置object-fit与width: 100%和height: 40vh,使之与card的尺寸相适应。object-fit: cover的神奇之处在于不会使图片变形。

图片标题定位
现在,根据Grid布局的作用,标题已经自然地流到了图像下方,假定它应该是在自己的 "单元格"里,而默认的grid items是沿着Y轴流动的。

利用 CSS transforms 属性来设置标题的初始位置:
由于我们使用的是p标签,所以我们也去掉了margin,以防止它对标题的高度产生不利影响。translate的值为100%,会使元素相对于它所放置的轴线100%移动。所以,translateY(100%)会有效地将标题 "向下"移出初始视图。
添加标题动画
我们在hover时触发动画,我们希望的看到的效果是可以顺利的触发显示动画,然后在返回到外面初始状态,有两个属性可以帮助实现这个目标:transition 和 will-change
我们定义了一个800ms过渡时间,并且设置ease-in过渡效果,然后我们使用will-change属性作为一个额外的提示,如果浏览器能够对该属性进行优化的话,我们会对变换属性进行修改,以实现更平滑的过渡。
:hover样式实际上将被放置在.gallery-card上,因为它是包含的元素,所以我们将添加一个 transform属性,用来将标题还原到初始状态
现在我们标题有了基本动画样式:

image Ken Burns 动画效果
你可能不知道这个名字,但你看到过这样的效果:慢速、流畅的平移和变焦组合的静止画面,由于被纪录片制作人肯-伯恩斯(Ken Burns)推广而得名。
利用我们已经介绍过的transition和tranform属性的原理,我们可以在.gallery-card__img上再次将它们结合起来,在悬停时也可以添加这种效果。
我们添加了额外的transform属性,将初始图像按比例放大1.2倍,以确保图像可以平移,如果不这样设置的话,一旦我们平移图片将无法覆盖原来的内容。
此外,我们首先设置一个5%的x偏移量,也就是将图像向右拉5%。这被应用到图片的缩放大小上。
接下来,我们在.gallery-card中添加了:hover transform,除了在x轴上向左拉回-1%,在y轴上向右拉回-3%之外,来实现缩放效果。
大家可以根据自己的情况来设置值的大小
还有一点,就是我们把过渡时长设置成了400ms的差值。我们可以把这个值作为标题的延时来添加。要注意的是,这个延迟适用于悬停过渡之前的过渡,而在过渡结束的时候,则是在悬停的时候。我个人很喜欢这种效果,因为这意味着两个地方的动画都会一起结束。
不要忘了 :focus
Hover对于使用鼠标的人来说是没问题,但是对于那些因为各种原因主要使用键盘导航的人来说呢?
li元素本身并不是一个可聚焦的元素,所以仅仅添加:focus样式并不能改变行为。
我们首先需要给每个li元素添加tabindex="0",这将使它们成为可聚焦元素。
你可以通过tab来测试触发动画效果
我们会删除tabindex="0"而是用 :focus达到同样的效果
Optional
这种风格还有一种效果--在图像的边框上有柔和的黑色渐变,我们可以使用box-shadow的inset的属性完成此操作。box-shadow无法直接作用于图像元素,因此我们将其应用于.gallery-card的:after伪元素上
设置 grid-area: card;来确保它的高度和宽度占据整个卡片的高度和宽度,此外还有一个z-index确保图片在容器上方。
这样做的副作用是,它覆盖了标题,但我们要多加一个z-index: 2;来提高标题的优先级。
codepen:
https://codepen.io/5t3ph/pen/xxwEXmE
版权声明: 本文为 InfoQ 作者【寇云】的原创文章。
原文链接:【http://xie.infoq.cn/article/7e24e93004a536e4391432b3b】。文章转载请联系作者。











评论