如何使用CSS,给你的图片添加揭露动画效果?
前言
何为揭露动画效果?顾名思义,当触发某种事件后,隐匿在后面的元素会慢慢浮现出来,如下图所示:

你可能会想,我们可以使用其他元素或伪元素,实现该动画效果。
但是我们将只使用<img>元素实现该效果,听起来似乎完全不可能,接下来,让我们共同揭开这神秘的面纱
初始化配置
我们给<img>元素设置尺寸
img {
--s: 200px; /*图片尺寸*/
width: var(--s);
height: var(--s);
box-sizing: border-box;
}
目前看起来一切都不复杂,我们为了简洁起见,使用了正方形图片,你也可以使用其他多维度图片。

注意: 必须明确设置
width和height,且不能使用aspect-ratio。这是强制性要求,这一点会在后面解释
box-sizing: border-box也很重要,在这个阶段,看不出它的作用,但我们在下一步将会阐述为何需要它
添加Padding
如果我们给已固定宽高的元素,添加padding-left: 100px,看看将会发生什么

由于我们给左侧设置了100px的padding,所以图片只有100px的内容空间了(即content area),这便是box-sizing: border-box的效果
MDN解释如下所示:
border-box告诉浏览器,你设置的border、padding都将被当做该元素的宽高。如果你设置某元素的宽度为100px,那么,这100px将会包括你添加的border、padding,内容空间便会被压缩至剩余的宽度内
现在,让我们设置padding等于图片宽度,将会发生什么呢?是的,图片将会消失不见。
我们在鼠标移入时,设置padding
img {
--s: 200px; /*图片尺寸*/
width: var(--s);
height: var(--s);
box-sizing: border-box;
cursor: pointer;
transition: .5s;
}
img:hover {
padding-left: var(--s);
}
body {
margin: 0;
min-height: 100vh;
display: grid;
place-content: center;
gap: 50px;
grid-auto-flow: column;
background: #C6E5D9;
}

我们可以看到CSS变量的重要性,我们在设置padding时,可直接使用该变量,而无需再次定义该值
添加背景色
紧接着上面的代码,我们给img添加背景色
img {
--s: 200px; /*图片尺寸*/
width: var(--s);
height: var(--s);
box-sizing: border-box;
cursor: pointer;
transition: .5s;
background: #542437;
}

当图片元素消失后,背景色将会覆盖整个元素,我们在图片元素时,看不到该背景色,但是我们可以在padding区域内看到背景色
我们的目标是,翻转图片,接下来我们会在初始的时候设置padding,在hover的时候呢,将padding置为0

效果与上面刚刚相反
这仍然不是我们想要的,但却离目标越来越近了。我们最后只欠缺一味作料,让我们的揭露动画看起来更完美!
添加object-fit和object-position
欠缺的地方是:需要避免图片被压缩。现在到了最后一步啦,我们将使用object-fit:cover来解决该问题
MDN这样阐述道:
当
替代内容填充元素的整个content盒子时,是维持着它的的长宽比(aspect ratio)。如果当前对象的长宽比,与盒子的长宽比不匹配,那么当前对象将会自行裁剪填充
上述内容有两点很重要:
替代内容会维持着它的长宽比:这意味着如果保持着图片的长宽比,它便不会被压缩。我们使用了正方形图片,那么它将会维持着正方图形填充当前元素的盒子区域...将会自行裁剪填充:当前图片将会填满整个内容区域(我们添加padding后,剩下的空间),如果它无法填充,我们对其进行裁剪
img {
--s: 200px; /*图片尺寸*/
width: var(--s);
height: var(--s);
box-sizing: border-box;
cursor: pointer;
transition: 1s;
background: #542437;
padding-left: var(--s);
object-fit: cover;
}

瞧见没?现在图片不再被压缩!无论我们添加或删除padding,它始终在内容区域维持着它的长宽比
现在,我们发现还有个问题,当前图片移动的很奇怪,现在让我们使用object-position,它的默认值为center,所以图片会始终在内容区域内裁剪居中。这便是它为何跟随动画移动。
接下来,我们会更改position,来确保图片不会移动。我们将会添加左侧padding,所以我们将会修改图片位置至右侧object-position: right
img {
--s: 200px; /*图片尺寸*/
width: var(--s);
height: var(--s);
box-sizing: border-box;
cursor: pointer;
transition: .5s;
background: #542437;
padding-left: var(--s);
object-fit: cover;
object-position: right;
}

我们已完成了揭露动画!我们无需覆盖层或多余的元素。我们只需使用简单的背景色,以及对图片位置的小技巧处理,便能获得完美的揭露动画效果。
我们可以随意地更新动画方向,通过调整padding和object-position。
下面是文章初始的动画效果及代码示例

img {
--s: 200px; /*图片尺寸*/
width: var(--s);
height: var(--s);
box-sizing: border-box;
cursor: pointer;
transition: .5s;
background: #542437;
object-fit: cover;
}
img.left {
object-position: right;
padding-left: var(--s);
background: #542437;
}
img.right {
object-position: left;
padding-right: var(--s);
background: #8A9B0F;
}
img.top {
object-position: bottom;
padding-top: var(--s);
background: #E94E77;
}
img.bottom {
object-position: top;
padding-bottom: var(--s);
background: #7A6A53;
}
img:hover {
padding: 0;
}
body {
margin: 0;
min-height: 100vh;
display: grid;
place-content: center;
gap: 50px;
grid-auto-flow: column;
background: #C6E5D9;
}
更多的揭露动画
我们可以拓展该技巧,来添加多种形式的动画效果。在这里,我们不再使用一边添加padding的方式,而是两边或所有边都添加padding

img {
--s: 200px; /*图片尺寸*/
width: var(--s);
height: var(--s);
box-sizing: border-box;
cursor: pointer;
transition: .5s;
}
img.center {
object-fit: none; /* 它允许替代内容维持着原有的尺寸 */
padding: calc(var(--s)/2);
background: #88C425;
}
img.vertical {
object-fit: cover; /* 亦可使用object-fit: none */
padding-block: calc(var(--s)/2);
background: #F07818;
}
img.horizontal {
object-fit: cover;
padding-inline: calc(var(--s)/2);
background: #AB3E5B;
}
/* 你可以使用padding的任意形式,需确保padding覆盖到整个区域
也需要确保正确地设置object-position和object-fit来创建固定图像的幻象
*/
img.random {
object-position: top left;
object-fit: none;
padding: 0 var(--s) var(--s) 0;
background: #0E2430;
}
img:hover {
padding: 0;
}
注意:在
img.center类内,我们使用object-fit: none,padding会将内容区域(content area)的宽高减至0,而在其他类里,我们要么减少高度值或宽度值,所以使用cover即可
MDN这样阐述道:
替代内容(
replaced content)不会被调整大小
为何我们不在所有示例内使用none?我们能这样用,它也是有效果的,但是有个缺点。none会考虑图片的本身尺寸,所以我们若使用none,是强制宽高等于图片本身尺寸,来获得对应的动画效果。但是cover与之不同,它仅仅维持着图片的尺寸比,来自适应区域。
当我们使用object-fit: none,图片并未被调整大小,而是维持着它的默认尺寸,这点不太好。而object-fit: cover会根据盒子空间,自动调整其大小,因为它只需考虑图片的尺寸比
尾声
我希望你们能喜欢这样的CSS小技巧。我们还可以使用这些小技巧,将黑白图片渐变至彩色效果

img {
--s: 200px;
width: var(--s);
height: var(--s);
box-sizing: border-box;
object-fit: cover;
background: var(--i) 50%/cover #000;
background-blend-mode: luminosity;
transition: .5s;
cursor: pointer;
}
img.left {
object-position: right;
padding-left: var(--s);
}
img.right {
object-position: left;
padding-right: var(--s);
}
img.top {
object-position: bottom;
padding-top: var(--s);
}
img.bottom {
object-position: top;
padding-bottom: var(--s);
}
img:hover {
padding: 0;
}
转载自:https://juejin.cn/post/7246935481615925303