图片与标题的 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】。文章转载请联系作者。
评论