如何使用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