本章将介绍与图片、视频等多媒体元素视觉表现相关的CSS新特性。

10.1 图片和视频元素的内在尺寸控制

图片或者视频等替换元素的内在尺寸100%适应于外部指定的尺寸,这就会导致在CSS设置的宽高比与内在尺寸的比例不一致的情况下,图片或视频会被拉伸。这些情况显然不是开发者希望看到的。在过去,这样的问题并没有特别好的解决办法,开发者往往利用具有内部尺寸的元素在没有指定高宽的情况下依然保持比例的特性,仅设置宽度值,或者仅设置高度值,让图片既有自适应的特性,又能保持比例。

但是,这种做法有一个缺点,那就是在第一次加载图片的时候,如果图片还没有加载完毕,浏览器会认为内在尺寸是0。例如:

img {
    width: 100%;
}

上面的img仅设置了宽度而没有设置高度,于是,在图片还没有加载完毕的时候,图片占据的高度是0;等图片加载完毕,高度又会恢复。这样一个突然的高度变化在视觉层面就表现为页面内容跳动出现,图片会不断触发重绘,不仅性能不佳,用户体验也不好。

为了应对上面这样的场景,开发者就设计了新的CSS属性,即object-fitobject- position属性。这两个CSS属性就表现而言,类似于background-sizebackground- position属性,都可以让图片的视觉区域在保持比例的情况下适应外部设定的尺寸,区别在于前两个属性控制内联图像,后两个属性控制背景图像

在实际开发中,object-fit很常用,object-position则很少被用到,因为默认的居中适应就是我们需要的效果。

这里先介绍一下超级好用的object-fit属性。

10.1.1 超级好用的object-fit属性

object-fit属性只支持关键字属性值,具体有5个值,语法如下:

object-fit: fill | contain | cover | none | scale-down

使用示例如下:

object-fit: fill;
object-fit: contain;
object-fit: cover;
object-fit: none;
object-fit: scale-down;

在这些关键字属性值中,大家要重点关注containcover这两个属性值,因为两者几乎占据了全部的object-fit属性使用场景。下面我就依次介绍一下每个属性值的具体含义。

1.fill

fill是默认值,表示“填充”,替换内容会拉伸,填满整个content-box的尺寸, 不保证保持原有的比例。例如,有一张图像的原始比例是4:3,然后应用了下面的CSS代码:

img {
    width: 200px; height: 200px;
    padding: 20px;
    border: 20px solid rgba(20, 30, 255, .5);
    object-fit: fill;
}

效果如图10-1所示,可以看到图像出现了明显的拉伸效果,且拉伸填充的区域是content-box区域。

图片 1

图10-1 fill关键字属性值下图片拉伸显示效果示意

2.contain

contain表示“包含”,替换内容保持原有尺寸比例,同时替换内容一定可以在content-box中完整显示,至少一个方向的尺寸和content-box保持一致。此关键字属性值可能会让content-box出现留白,例如:

img {
    width: 200px; height: 200px;
    padding: 20px;
    border: 20px solid rgba(20, 30, 255, .5);
    object-fit: contain;
}

效果如图10-2所示,图片的上方和下方出现了留白。

说明: E:\wamp\www\sp\book\cn\images\一校新素材\10_2-object-fit-contain.png10_2-object-fit-contain

图10-2 contain关键字属性值下图片完整显示同时显示区域留白示意

3.cover

cover表示“覆盖”,替换内容同样会保持原始的尺寸比例,同时替换内容会完全覆盖content-box区域,至少一个方向的尺寸和content-box保持一致。此关键字可能会让替换内容的部分区域不可见,例如:

img {
    width: 200px; height: 200px;
    padding: 20px;
    border: 20px solid rgba(20, 30, 255, .5);
    object-fit: cover;
}

效果如图10-3所示,图片完全覆盖显示区域,同时图片左右两边有部分区域被隐藏了。

图片 3

图10-3 cover关键字属性值下图片完全覆盖显示区域示意

4.none

none表示替换内容的尺寸显示为原始的尺寸,无视外部的尺寸设置。如果图片尺寸较小,就会在四周产生大量留白;如果图片尺寸较大,则会有较大面积的图片区域被剪裁。在实际开发中,此关键字很少被使用

5.scale-down

scale-down的样式表现就好像依次设置了nonecontain关键字,然后选取呈现的尺寸较小的那个效果。例如:

img {
    width: 200px; height: 200px;
    padding: 20px;
    border: 20px solid rgba(20, 30, 255, .5);
    object-fit: scale-down;
}

效果如图10-4所示。当图片尺寸足够大的时候,样式表现等同于contain关键字的样式表现,如图10-4左侧所示;如果图片尺寸较小,则样式表现等同于none关键字的样式表现,如图10-4右侧所示。

说明: E:\wamp\www\sp\book\cn\images\10\10_4-object-fit-scale-down.png10_4-object-fit-scale-down

图10-4 scale-down关键字属性值在不同尺寸图片下的显示效果示意

读者可以在浏览器中进入 https://demo.cssworld.cn/new/10/1-1.php 页面,或者扫描右侧的二维码查看以上5个关键字值的效果。

在实际开发中,==通常缩略图使用cover关键字,列表图使用contain关键字,全屏大图预览使用scale-down关键字==。

object-fit属性在现代浏览器中的兼容性非常好,Android 4.4.4就开始支持了,在移动端可以放心使用。

10.1.2 理解object-position属性的作用规则

object-position要比object-fit单纯得多,用于控制替换内容的位置object- position的初始值是50% 50%,也就是说默认是居中效果。所以,无论object-fit的值是哪一个关键字属性值,图片都是水平、垂直居中的。因此,要实现尺寸大小不固定图片的水平、垂直居中效果,可以试试先将<img>元素的宽度设置为容器的宽度大小,然后设置object-fit:none

background-position类似,object-position的值类型为<position>,因此object- position属性的定位能力还是很强的。例如,让替换内容一直定位在content-box区域的右下角:

object-position: 100% 100%;

又如,让替换元素在相对于content-box区域右下角20px 10px的地方定位:

object-position: right 20px bottom 10px;

效果如图10-5所示,均符合预期表现。

说明: E:\wamp\www\sp\book\cn\images\10\10_5-object-position-basic.png10_5-object-position-basic

图10-5 object-position属性基本效果示意

读者可以在浏览器中进入 https://demo.cssworld.cn/new/10/1-2.php 页面,或者扫描右侧的二维码查看效果。

就我个人而言,我经常将object-position属性用在用户头像的显示上。例如,服务器存储的用户头像是3∶4的,而设计师设计的头像是1∶1的,此时,为了让用户头像中的脸部尽可能出现在视区中,我会使用object-position属性进行设置,例如:

.avatar {
    object-fit: cover;
    object-position: top;
}

Img Sprites技术

object-position是一个被低估的CSS属性,过去使用background-position定位实现的CSS Sprites技术和配合animation属性实现的无损Gif模拟技巧,现在都可以使用object-position属性实现,我称之为“Img Sprites技术”。

例如,5.4.8节演示的暂停“心花怒放”效果的案例就可以改用<img>元素实现,HTML和CSS代码如下:

<img class="love" src="heart-animation.png">
.love {
    width: 100px; height: 100px;
    object-fit: cover;
    animation: heart-burst steps(28) .8s infinite both;
}
@keyframes heart-burst {
    0% {
        object-position: 0%;
    }
    100% {
        object-position: 100%;
    }
}

就代码量而言,这个方法要比使用background- position定位实现的方法更简洁。最终效果如图10-6所示。

图片 6|57

图10-6 object-position属性实现的无损gif动图效果示意

最终效果是一个动画效果,读者可以在浏览器中进入 https://demo.cssworld.cn/new/10/1-3.php 页面,或者扫描右侧的二维码查看。

使用object-position实现上面效果的优势除代码更简洁、尺寸控制更方便之外,还有一个很大的优点就是可以使用<img>元素诸多内置的特性。例如想要在CSS中设置background-image图像实现懒加载是成本比较高的一件事情,但是,如果设置的是<img>内联图像,那么只需要一个loading属性就可以实现懒加载,例如:

<img src="heart-animation.png" loading="lazy">