在 Web 文档中,一个常见的问题涉及在同一位置显示不同大小的图像(或视频)。也许您正在编写一个接受用户提交的动态图库应用程序。您无法保证每个人都会上传完全相同纵横比的图像,那么您该怎么办呢?
让纵横比失真以适应包含的替换元素几乎总是看起来很糟糕。并且每次动态裁剪或调整大小可能比您能够实现的工作量更大。(例如,也许您正在使用 CMS 并且没有权限编辑除页面内容以外的任何内容。)
该 CSS 图像值和替换内容 模块提供了名为 object-fit 的属性,它解决了此类问题,以及 object-position 属性,它设置元素内部内容的水平和垂直位置。
这些元素在现代浏览器中获得了不错的支持(IE 除外)。在本文中,我们将介绍一些如何使用它们的示例。
注意:object-fit
可用于 SVG 内容,但也可以通过在 SVG 本身设置 preserveAspectRatio=""
属性来实现相同的效果。
object-fit 和 object-position 如何工作?
您可以成功地将 object-fit
应用于任何替换元素,例如
img {
height: 100px;
width: 100px;
object-fit: contain;
}
object-fit
的五个可能值为:
contain
:内容(例如图像)将调整大小,使其在保留固有纵横比的情况下完全显示,但仍适合元素设置的尺寸。fill
:内容将扩展以完全填充为元素设置的尺寸,即使这会破坏其纵横比。cover
:保留内容的纵横比,但更改宽度和高度,以便内容完全覆盖元素。较小的一个被设置为完全适合元素,较大的一个超出元素并被裁剪。none
:完全忽略元素上设置的任何高度或宽度,而只使用替换元素内容的固有尺寸。scale-down
:内容的大小如同指定了none
或contain
,以哪一个会导致更小的替换元素大小。
object-position
的工作方式与 background-position 对背景图像的工作方式完全相同;例如
img {
height: 100px;
width: 100px;
object-fit: contain;
object-position: top 70px;
}
百分比有效,但它们实际上是针对可用空间的剩余部分计算的——元素的宽度与替换内容的最终渲染宽度之间的差值。因此,object-position: 50% 50%
(默认值)将始终精确地居中替换元素。此外,object-position: 0% 0%
始终表示与左上角对齐,object-position: 100% 100%
始终表示与右下角对齐,等等。
关键字 top
、center
、right
等实际上只是 0%、50%、100% 等的便捷别名。
注意:您可以在我们的基本示例页面中看到一些 object position 示例。
不同 object-fit 值的效果
以下代码示例显示了不同 object-fit
值的效果。
使用 object-fit: contain 为图像添加黑边
有时被称为黑边,在某些情况下,您需要保留页面上图像的纵横比,但使其适合同一区域。例如,您可能有一个内容管理系统,允许您上传电子商务网站上的产品或图像库的图像,以及许多不同的内容作者。他们可能会上传大致正确大小的图像,但尺寸并不总是精确的,并且您希望将每个图像都放入相同数量的空间中。
具有纵横比偏移的图像通常看起来很糟糕,因此您可以使用 object-fit: contain
为其添加黑边(object-fit: contain 示例)。
img {
width: 480px;
height: 320px;
background: black;
}
.contain {
object-fit: contain;
}
使用 object-fit:cover 裁剪图像
另一种解决方案是保持纵横比,但将每个图像裁剪到相同大小,使其完全覆盖 <img>
元素,任何溢出都将被隐藏。这可以使用 object-fit:cover
轻松完成(object-fit: cover 示例)。
.cover {
object-fit: cover;
}
使用 object-fit: fill 覆盖视频的纵横比
反过来,也可以获取视频并强制其更改纵横比。也许您的一些内容编辑器的视频具有错误的纵横比,并且您希望在一次简单的操作中快速修复它们?
以以下视频图像为例
<video controls="controls" src="windowsill.webm"
width="426" height="240">
…
</video>
它看起来会很糟糕:视频会显示为黑边,因为 <video>
元素始终尝试保持源文件的固有纵横比。我们可以通过应用 object-fit: fill
来解决此问题(object-fit: fill 示例)。
.fill {
object-fit: fill;
}
这会覆盖视频的固有纵横比,强制其完全填充 <video>
元素,以便正确显示。
有趣的过渡效果
将 object-fit
和 object-position
与 CSS 过渡结合使用可以为图像或视频库带来一些非常有趣的效果。例如
.none {
width: 200px;
height: 200px;
overflow: hidden;
object-fit: none;
object-position: 25% 50%;
transition: 1s width, 1s height;
}
.none:hover, .none:focus {
height: 350px;
width: 350px;
}
仅显示图像的一小部分,并且当元素聚焦/悬停时,它会增长以显示更多图像(object-fit: none 示例)。
这是因为通过在 <img>
上设置 object-fit: none
,我们使内容完全忽略之前设置的任何宽度和高度,并溢出元素的侧面。然后,我们使用 overflow: hidden 来裁剪任何溢出的内容。然后使用过渡在悬停/聚焦时平滑地增加 <img>
元素的大小,从而显示更多图像。
图库示例
为了展示 object-fit
的稍微更实际的用法,我们创建了一个 图库示例。
16 张图像通过 XHR 加载,并作为 ObjectURL 插入到图像中。
for(i = 1; i <= thumbs.length ; i++) {
var requestObj = 'images/pic' + i + '.jpg';
retrieveImage(requestObj,i-1);
}
function retrieveImage(requestObj,imageNo) {
var request = new XMLHttpRequest();
request.open('GET', requestObj, true);
request.responseType = 'blob';
request.onload = function() {
var objectURL = URL.createObjectURL(request.response);
thumbs[imageNo].setAttribute('src',objectURL);
thumbs[imageNo].onclick = function() {
...
}
}
request.send();
}
依次为每个图像提供一个 onclick
处理程序,以便在单击时,图像以全尺寸显示,填充屏幕(最初在 CSS 中设置为 display: none;
的主图像将被赋予 blowup
类,这使得它显示并填充整个屏幕;然后将主图像的 src
设置为与单击的缩略图相同的 ObjectURL)。
thumbs[imageNo].onclick = function() {
mainImg.setAttribute('src',objectURL);
mainImg.className = 'blowup';
for(i = 0; i < thumbs.length; i++) {
thumbs[i].className = 'thumb darken';
}
}
单击全尺寸图像会使其再次消失。
mainImg.onclick = function() {
mainImg.className = 'main';
for(i = 0; i < thumbs.length; i++) {
thumbs[i].className = 'thumb';
}
}
所有调整大小都是使用百分比完成的,以便无论屏幕尺寸如何,网格都保持比例。
body > div {
height: 25%;
}
.thumb {
float: left;
width: 25%;
height: 100%;
object-fit: cover;
}
注意:所有缩略图都已设置为 tabindex="0"
以便通过 Tab 键聚焦(您可以通过在任何元素上设置 tabindex="0"
来使其出现在页面 Tab 顺序中),并且使全尺寸图像出现的 onclick
处理程序已与 onfocus
处理程序一起使用,以提供基本的键盘可访问性。
thumbs[imageNo].onfocus = function() {
mainImg.setAttribute('src',objectURL);
mainImg.className = 'blowup';
for(i = 0; i < thumbs.length; i++) {
thumbs[i].className = 'thumb darken';
}
}
巧妙的部分在于 object-fit
的用法。
- 缩略图:这些缩略图已设置
object-fit: cover
,以便所有图像缩略图都将以相同的大小、正确的纵横比显示,但裁剪的量不同。这看起来相当不错,并且在您调整窗口大小时会产生不错的效果。 - 主图像:此图像已设置
object-fit: contain
和object-position: center
,以便它能够以完整、正确的纵横比和尽可能大的尺寸显示。
关于 Chris Mills
Chris Mills 是 Mozilla 的高级技术作家,他撰写有关开放式 Web 应用、HTML/CSS/JavaScript、A11y、WebAssembly 等方面的文档和演示。他喜欢捣鼓 Web 技术,并在会议和大学偶尔发表技术演讲。他曾为 Opera 和 W3C 工作,喜欢演奏重金属鼓和饮用好啤酒。他和他的妻子以及三个可爱的孩子住在英国曼彻斯特附近。
15 条评论