likes
comments
collection
share

如何使用CSS,给你的图片添加揭露动画效果?

作者站长头像
站长
· 阅读数 17

前言

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

如何使用CSS,给你的图片添加揭露动画效果?

你可能会想,我们可以使用其他元素或伪元素,实现该动画效果。

但是我们将只使用<img>元素实现该效果,听起来似乎完全不可能,接下来,让我们共同揭开这神秘的面纱

初始化配置

我们给<img>元素设置尺寸

    img {
        --s: 200px; /*图片尺寸*/

        width: var(--s);
        height: var(--s);
        box-sizing: border-box;
    }

目前看起来一切都不复杂,我们为了简洁起见,使用了正方形图片,你也可以使用其他多维度图片。

如何使用CSS,给你的图片添加揭露动画效果?

注意: 必须明确设置widthheight,且不能使用aspect-ratio。这是强制性要求,这一点会在后面解释

box-sizing: border-box也很重要,在这个阶段,看不出它的作用,但我们在下一步将会阐述为何需要它

添加Padding

如果我们给已固定宽高的元素,添加padding-left: 100px,看看将会发生什么

如何使用CSS,给你的图片添加揭露动画效果?

由于我们给左侧设置了100pxpadding,所以图片只有100px的内容空间了(即content area),这便是box-sizing: border-box的效果

MDN解释如下所示:

border-box告诉浏览器,你设置的borderpadding都将被当做该元素的宽高。如果你设置某元素的宽度为100px,那么,这100px将会包括你添加的borderpadding,内容空间便会被压缩至剩余的宽度内

现在,让我们设置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,给你的图片添加揭露动画效果?

我们可以看到CSS变量的重要性,我们在设置padding时,可直接使用该变量,而无需再次定义该值

添加背景色

紧接着上面的代码,我们给img添加背景色

    img {
        --s: 200px; /*图片尺寸*/

        width: var(--s);
        height: var(--s);
        box-sizing: border-box;
        cursor: pointer;
        transition: .5s;
        background: #542437;
    }

如何使用CSS,给你的图片添加揭露动画效果?

当图片元素消失后,背景色将会覆盖整个元素,我们在图片元素时,看不到该背景色,但是我们可以在padding区域内看到背景色

我们的目标是,翻转图片,接下来我们会在初始的时候设置padding,在hover的时候呢,将padding置为0

如何使用CSS,给你的图片添加揭露动画效果?

效果与上面刚刚相反

这仍然不是我们想要的,但却离目标越来越近了。我们最后只欠缺一味作料,让我们的揭露动画看起来更完美!

添加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;
    }

如何使用CSS,给你的图片添加揭露动画效果?

瞧见没?现在图片不再被压缩!无论我们添加或删除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;
    }

如何使用CSS,给你的图片添加揭露动画效果?

我们已完成了揭露动画!我们无需覆盖层或多余的元素。我们只需使用简单的背景色,以及对图片位置的小技巧处理,便能获得完美的揭露动画效果。

我们可以随意地更新动画方向,通过调整paddingobject-position

下面是文章初始的动画效果及代码示例

如何使用CSS,给你的图片添加揭露动画效果?

    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

如何使用CSS,给你的图片添加揭露动画效果?

    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: nonepadding会将内容区域(content area)的宽高减至0,而在其他类里,我们要么减少高度值或宽度值,所以使用cover即可

MDN这样阐述道:

替代内容(replaced content)不会被调整大小

为何我们不在所有示例内使用none?我们能这样用,它也是有效果的,但是有个缺点。none会考虑图片的本身尺寸,所以我们若使用none,是强制宽高等于图片本身尺寸,来获得对应的动画效果。但是cover与之不同,它仅仅维持着图片的尺寸比,来自适应区域。

当我们使用object-fit: none,图片并未被调整大小,而是维持着它的默认尺寸,这点不太好。而object-fit: cover会根据盒子空间,自动调整其大小,因为它只需考虑图片的尺寸比

尾声

我希望你们能喜欢这样的CSS小技巧。我们还可以使用这些小技巧,将黑白图片渐变至彩色效果

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