我们并不总是能够为 HTML 元素加载不同尺寸的图像。如果我们使用的宽度和高度不符合图像的纵横比,图像可能会被压缩或拉伸。这不是一个好的结果,不过我们可以通过对
img
元素使用 object-fit
或使用 background-size
来解决这个问题。
首先,让我们定义一下这个问题。请看下图:
为什么会这样?
每张图片都有一个纵横比,浏览器会用该图像填充其所在的容器。如果图像的纵横比与为其指定的宽度和高度不同,那么结果将是图像被压缩或拉伸。
解决方案
当图像的纵横比与容器的宽度和高度不匹配时,我们并不总是需要添加不同尺寸的图像。在深入讨论 CSS 解决方案之前,我想展示一下过去我们在照片编辑软件中是如何解决这个问题的:
首先,我们会将图像垂直居中,然后通过遮罩进行裁剪。这样可以保持图像的纵横比,并防止图像被压缩。
现在我们已经理解了这个过程的原理,让我们来看一下在浏览器中是如何实现的。(剧透:这更简单!)
CSS object-fit
object-fit
属性定义了像 img
或 video
这样的替换元素的内容应如何调整大小以适应其容器。object-fit
的默认值是 fill
,这可能会导致图像被压缩或拉伸。
让我们来看看可能的取值。
object-fit
的可能值
object-fit: contain
在这种情况下,图像将调整大小以适应容器的纵横比。如果图像的纵横比与容器不匹配,它会被信箱化处理(即在空白区域添加黑边或白边)。
当使用 object-fit: contain
时,图像会被信箱化或相应地调整大小。
object-fit: cover
在这里,图像也会调整大小以适应容器的纵横比。如果图像的纵横比不匹配,则图像将被裁剪以适应容器。
当使用 object-fit: cover
时,图像会被裁剪或相应地调整大小。
object-fit: fill
使用此选项时,图像会调整大小以适应容器的纵横比。如果图像的纵横比不匹配,则会被压缩或拉伸。我们通常不希望这样。
当使用 object-fit: fill
时,图像会被压缩、拉伸或相应地调整大小。
object-fit: none
在这种情况下,图像根本不会调整大小,不会被拉伸或压缩。它的行为类似于 cover
,但不会遵循容器的纵横比。
当使用
object-fit: none
时,如果图像的尺寸不同,它不会被调整大小。(大图预览)
除了 object-fit
,我们还有 object-position
属性,负责将图像在容器内进行定位。
object-position
的可能值
object-position
属性与 CSS 的 background-position
属性类似:
大多数情况下,默认值会被使用(即
center
或 50% 50%
)
当容器的纵横比在垂直方向上更大时,top
和 bottom
关键字也可以使用:
-
object-position: top
(左侧)和object-position: bottom
(右侧)对比。
CSS background-size
使用 background-size
时,主要区别在于我们处理的是背景,而不是 HTML 的 img
元素。
background-size
的可能值
background-size: auto
使用 auto
时,图像将保持默认尺寸:
请记住,默认尺寸有时可能会导致图像模糊(如果图像过小的话)。
background-size: cover
在这种情况下,图像将调整大小以适应容器。如果纵横比不同,图像将被遮罩处理以适应。
使用
background-size: cover
时,请确保考虑图像的纵横比。
background-size: contain
在这种情况下,图像将调整大小以适应容器。如果纵横比不匹配,图像会像下一个示例中那样被信箱化处理:
background-size: contain
会调整图像大小以适应容器。
关于 background-position
,它的工作方式类似于 object-position
。唯一的区别是,object-position
的默认位置与 background-position
的默认位置不同。
翻译:
何时不应使用 object-fit
或 background-size
如果元素或图像被设置了固定高度,并且应用了 background-size: cover
或 object-fit: cover
,那么在某些情况下,图像会变得过宽,导致丢失重要细节,这可能会影响用户对图像的感知。
请看以下例子,其中图像被赋予了固定高度:
.card__thumb {
height: 220px;
}
下图展示了一个图像过宽的例子,因为图像的高度是固定的,而卡片容器太宽。
如果卡片容器过宽,将导致右侧所示的结果(图像过宽)。这是因为我们没有指定纵横比。
解决方法只有两个。第一个方法是使用填充技巧来创建内在比例:
.card__thumb {
position: relative;
padding-bottom: 75%;
height: 0;
}
.card__thumb img {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
第二个解决方法是使用新的 aspect-ratio
CSS 属性。通过它,我们可以这样做:
.card__thumb img {
aspect-ratio: 4 / 3;
}
用例与示例
用户头像
object-fit: cover
的一个完美用例就是用户头像。头像的纵横比通常是正方形,将图像放入正方形的容器中可能会导致图像变形。
- 没有
object-fit
和使用object-fit: cover
的用户头像对比。
.c-avatar {
object-fit: cover;
}
标志列表
展示企业的客户名单很重要。我们通常会使用标志,但由于标志大小各异,我们需要一种方法在不扭曲图像的情况下调整大小。
幸运的是,object-fit: contain
是一个很好的解决方案。
.logo__img {
width: 150px;
height: 80px;
object-fit: contain;
}
- 一个标志列表:Airbnb、Domino's Pizza、Apple Pay、Amazon
使用 object-fit: contain
可以帮助我们调整客户标志的大小,而不扭曲图像。
文章缩略图
这是一个非常常见的用例。文章缩略图的容器可能并不总是包含具有相同纵横比的图像。这个问题本应由内容管理系统(CMS)解决,但并不总是如此。
.article__thumb {
object-fit: cover;
}
通过 object-fit: cover
来调整文章缩略图。
超级背景
在这个用例中,决定使用 img
元素还是 CSS 背景取决于以下问题:
- 这个图像是否重要?如果 CSS 出于某种原因被禁用,我们希望用户看到图像吗?
- 还是图像仅仅是装饰性的?
根据答案,我们可以决定使用哪个功能。如果图像很重要:
- 使用超级背景的用例
假设图像很重要,因为这是一个与食物相关的网站。😉
<section class="hero">
<img class="hero__thumb" src="thumb.jpg" alt="" />
</section>
.hero {
position: relative;
}
.hero__thumb {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
如果图像是装饰性的,我们可以使用 background-image
:
.hero {
position: relative;
background-image: linear-gradient(to top, #a34242, rgba(0,0,0,0), url("thumb.jpg"));
background-repeat: no-repeat;
background-size: cover;
}
这种情况下,CSS 代码会更简短。确保任何放置在图像上的文字都可读且易于访问。
使用 object-fit: contain
为图像添加背景
你知道可以为 img
添加背景颜色吗?在使用 object-fit: contain
时,我们可以从中受益。
在下面的示例中,我们有一个图像网格。当图像和容器的纵横比不同,背景颜色将会显示出来。
img {
object-fit: contain;
background-color: #def4fd;
}
- 使用
object-fit: contain
为图像添加背景颜色。
视频元素
你是否曾需要将视频用作背景?如果是,那么你可能希望它占据父容器的全部宽度和高度。
.hero {
position: relative;
background-color: #def4fd;
}
.hero__video {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
- 在默认情况下,视频的
object-fit
值是contain
。如图所示,即使视频有position: absolute
、width: 100%
和height: 100%
,视频仍然无法覆盖整个背景。
要让视频完全覆盖其父容器的宽度和高度,我们需要覆盖默认的 object-fit
值:
.hero__video {
/* 其他样式 */
object-fit: cover;
}
- 现在,视频覆盖了其父容器的全部宽度和高度。
结论
正如我们所见,object-fit
和 background-size
在处理不同图像纵横比时非常有用。我们不总是能够控制每个图像的完美尺寸,这时这两个 CSS 功能就发挥了作用。
在选择 img
元素和 CSS 背景之间时要注意可访问性。如果图像是纯装饰性的,使用 CSS 背景更合适;否则,使用 img
更合适。
网友评论