讓圖片完美適應(yīng):掌握 CSS 的 Object-Fit 與 Object-Position
在CSS中,我們可以使用 background-size 和background-position屬性為背景圖像設(shè)置大小和位置。而 object-fit 和 object-position 屬性則允許我們對(duì)嵌入的圖像(以及其他替代元素,如視頻)做類(lèi)似的操作。在本文中,我們將深入探討如何使用 object-fit 將圖像適應(yīng)到特定的空間中,以及如何使用 object-position 在該空間中進(jìn)行精確定位。
object-fit 作用
有時(shí),圖像的大小超出了我們希望的空間。在過(guò)去,我們要么在圖像編輯器中裁剪圖像,要么通過(guò)設(shè)置寬度/或高度約束來(lái)調(diào)整圖像大小(這不是一個(gè)完美的選擇),或者執(zhí)行某種復(fù)雜的裁剪,或者可能轉(zhuǎn)而使用背景圖像(如果圖像不僅僅是為了裝飾的話(huà))。
object-fit 屬性為圖像提供了background-size為背景圖像所做的功能:它為圖像在指定區(qū)域內(nèi)的顯示提供了選項(xiàng),如果需要,可以隱藏部分圖像。這個(gè)指定的區(qū)域可能有固定的寬度和高度,或者可能是一個(gè)更具響應(yīng)性的空間,如根據(jù)瀏覽器視口大小變化的網(wǎng)格區(qū)域。
object-fit 工作原理
每個(gè)HTML元素都有自己的“content box”,代表它所占據(jù)的空間。默認(rèn)情況下,圖像的內(nèi)容框與圖像的自然尺寸相匹配。
當(dāng)我們?yōu)閳D像應(yīng)用不同的寬度和/或高度時(shí),我們實(shí)際上是在改變內(nèi)容框的尺寸。如果內(nèi)容框的尺寸發(fā)生變化,圖像仍然會(huì)填充內(nèi)容框。所以,如果我們有一個(gè)300px乘300px的圖像,并將其尺寸設(shè)置為300px乘200px,圖像會(huì)出現(xiàn)扭曲。
object-fit 屬性為我們提供了圖像在該調(diào)整后的內(nèi)容框內(nèi)顯示的選項(xiàng)。而不是讓它出現(xiàn)扭曲,我們可以隱藏圖像的一部分,或者強(qiáng)制圖像只部分填充其內(nèi)容框,這樣它就完全可見(jiàn)且不會(huì)扭曲。
設(shè)置
為了詳細(xì)說(shuō)明 object-fit 屬性的工作原理,我們將圖像放在一個(gè)使用Grid布局居中的 div 中。div 有一個(gè)棕色的背景,以及由::before偽元素提供的虛線(xiàn)邊框,這將幫助我們理解圖像發(fā)生了什么。
// html
<article>
<div>
</div>
</article>
// css
article {
display: grid;
grid-template: 1fr 200px 1fr / 1fr 300px 1fr;
height: 100vh;
}
div {
grid-row: 2;
grid-column: 2;
background-color: brown;
position: relative;
}
div::before {
content: "";
position: absolute;
inset: -5px;
border: 5px dashed white;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #30353b;
}
事例地址:https://codepen.io/SitePoint/pen/PoxRojJ
在圖像演示中,我們將使用以下圖像,其自然尺寸為 400px x 600px .
我們的圖像比我們的div大得多,如果我們將圖像放在div內(nèi),它會(huì)溢出,如下所示。
我們的目標(biāo)是防止圖像從其容器中爆裂出來(lái),但也要讓它舒適地適應(yīng)其中,object-fit 將幫助我們做到這一點(diǎn)。
如果我們使用背景圖像,我們可以設(shè)置類(lèi)似background-size: cover,背景圖像將被限制在容器的區(qū)域內(nèi)。但正如我們所看到的,為了讓 object-fit 發(fā)揮作用,我們首先需要在圖像的內(nèi)容框上定義一個(gè)與其自然大小不同的高度和寬度。在下面的示例中,我們將圖像的寬度和高度限制為100%,這樣其內(nèi)容框就與容器div的大小相匹配:
img {
width: 100%;
height: 100%;
}
圖像及其內(nèi)容框現(xiàn)在緊密地適應(yīng)容器,但圖像嚴(yán)重扭曲。這就是object-fit的魔法來(lái)拯救我們的地方,所以讓我們看看它有什么提供。
使用 object-fit 將圖像適應(yīng)容器
object-fit 屬性為我們提供了五個(gè)主要的關(guān)鍵字值,以確定我們的圖像如何在其容器內(nèi)顯示。其中兩個(gè)關(guān)鍵字——cover和contain——與它們的background-size對(duì)應(yīng)項(xiàng)執(zhí)行相同的角色。
object-fit: cover
cover 值強(qiáng)制圖像完全覆蓋容器的區(qū)域,盡可能多地顯示圖像,而不會(huì)扭曲它:
img {
width: 100%;
height: 100%;
object-fit: cover;
}
因?yàn)閳D像相當(dāng)高,我們看到的是其完整的寬度,但不是其完整的高度,如下圖所示。
cover 值確保圖像的較窄部分完全填充容器。
值得注意的是,圖像的定位。與background-position默認(rèn)為0 0(從容器的左上角定位背景圖像)不同,object-position 的默認(rèn)值是50% 50%,將圖像居中于其內(nèi)容框。當(dāng)我們稍后查看object-position屬性時(shí),我們將學(xué)習(xí)如何指定圖像的可見(jiàn)部分。
object-fit: contain
contain 值強(qiáng)制圖像完全適應(yīng)其內(nèi)容框,但不會(huì)扭曲。圖像保持其自然的寬高比,因此不會(huì)填滿(mǎn)其容器:
img {
width: 100%;
height: 100%;
object-fit: contain;
}
你可能會(huì)認(rèn)為,只需在圖像上設(shè)置height: 100%就可以得到上面的相同結(jié)果。但實(shí)際上并不完全如此,因?yàn)檫@樣會(huì)使圖像定位到左邊,而不是居中,這是object-fit的默認(rèn)設(shè)置。結(jié)合object-position,object-fit為圖像在容器內(nèi)的定位提供了更多的選項(xiàng)。
object-fit: none
none 屬性允許圖像保持其自然的原始尺寸。只有可以適應(yīng)調(diào)整后的內(nèi)容框的部分才是可見(jiàn)的。
與object-fit: cover不同,我們的圖像不會(huì)被強(qiáng)制在至少一個(gè)軸上完全可見(jiàn)。原始圖像的寬度和高度都大于內(nèi)容框,所以它在兩個(gè)方向上都溢出,如下圖所示。none 值保持圖像的正常大小,因此在容器中看不到圖像的頂部、底部和兩側(cè)。
再次注意,默認(rèn)情況下,圖像的中心與內(nèi)容框的中心對(duì)齊。
還要注意,object-fit: none 并不意味著 object-fit 什么都不做。正如我們所看到的,與完全沒(méi)有 object-fit 設(shè)置相比,它做了很多工作。
object-fit: scale-down
scale-down 屬性與 none 或 contain 相同。它選擇使圖像顯示得更小的那個(gè)。
顯然,在我們當(dāng)前的示例中,它會(huì)選擇 contain,因?yàn)槲覀兊娜萜鞅葓D像小。如果我們的容器比圖像大,none 會(huì)占主導(dǎo)地位,圖像會(huì)保持其自然大小,而不是在一個(gè)方向上填充容器,如你在這個(gè)CodePen演示中所看到的。
object-fit: fill
如果我們?cè)谘菔局袑?nbsp;object-fit 值更改為 fill,就好像根本沒(méi)有設(shè)置 object-fit。這是因?yàn)?,默認(rèn)情況下,圖像無(wú)論設(shè)置了什么尺寸都會(huì)填充其內(nèi)容框。
因?yàn)?nbsp;fill 屬性可能會(huì)扭曲圖像,所以在大多數(shù)情況下,它可能不是最好的選擇。
使用 object-fit 而不使用容器
在上面的示例中,我們一直在使用 object-fit 來(lái)調(diào)整 div 容器內(nèi)的圖像大小,但我們?cè)趯?shí)踐中看到的原理在沒(méi)有容器的情況下同樣適用。重要的是圖像的內(nèi)容框的大小以及圖像在該框內(nèi)的顯示方式。
例如,我們可以將以下CSS應(yīng)用于圖像,而不需要任何周?chē)?nbsp;div:
img {
width: 300px;
height: 300px;
object-fit: contain;
}
嘗試更改上面的Pen中object-fit屬性的值為 cover、fill、scale-down 和 none,看看每個(gè)的行為如何。結(jié)果與圖像設(shè)置為寬度和高度為 100% 并包含在一個(gè)設(shè)置為 300px 乘300px 的 div 中的結(jié)果相同。
在響應(yīng)式布局中使用 object-fit
object-fit 屬性在圖像的指定區(qū)域的尺寸響應(yīng)瀏覽器視口大小的情況下可能最有用。以下演示將我們的圖像分配給一個(gè)特定的、靈活的網(wǎng)格區(qū)域:
img {
width: 100%;
height: 100%;
object-fit: cover;
grid-row: 2 / 3;
grid-column: 2 / 3;
}
article {
display: grid;
grid-template: 5% 1fr 10% / 40% 1fr 40%;
height: 100vh;
}
事例地址:https://codepen.io/SitePoint/pen/JjeLWXW
隨著視口和網(wǎng)格區(qū)域的擴(kuò)展和收縮,cover 值確保圖像始終很好地適應(yīng)其網(wǎng)格區(qū)域,改變圖像的可見(jiàn)部分,使其永遠(yuǎn)不會(huì)扭曲。
使用 object-position 設(shè)置圖像的位置
正如 background-position 用于設(shè)置容器內(nèi)背景圖像的位置一樣,object-position 屬性用于控制圖像元素在其自己的內(nèi)容框內(nèi)的位置。
正如我們所看到的,object-position 默認(rèn)為 50% 50%,這意味著圖像的中心與其內(nèi)容框的中心對(duì)齊。我們可以使用一系列的關(guān)鍵字值(如 top、bottom、left、right、center)或使用長(zhǎng)度值(如px、em或%)或兩者的組合來(lái)更改這一點(diǎn)。
假設(shè)我們現(xiàn)在想要從右下角定位我們的圖像。我們可以使用關(guān)鍵字 right bottom,或百分比值100% 100%:
img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: right bottom; /* or 100% 100% */
}
我們還可以使用像像素或 ems這樣的單位偏移圖像從其容器。例如:
img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: 20px 2em; /* 20px from left and 2em from top */
}
我們可以通過(guò)結(jié)合單位和關(guān)鍵字來(lái)從右下角進(jìn)行類(lèi)似的偏移,如下所示:
img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: right 20px bottom 2em; /* 20px from right and 2em from bottom */
}
我們已經(jīng)看到,我們可以使用百分比來(lái)定位圖像在其內(nèi)容框中。與 background-position 屬性一樣,使用百分比與 object-position 可能會(huì)有點(diǎn)混淆。object-position 為 50% 50% 意味著圖像的中心與其內(nèi)容框的中心在水平和垂直軸上對(duì)齊。
如果我們將 object-position 設(shè)置為 20% 40%,這意味著圖像左邊 20% 的垂直線(xiàn)與內(nèi)容框左邊20% 的垂直線(xiàn)重合,圖像頂部40% 的水平線(xiàn)與內(nèi)容框頂部40%的水平線(xiàn)重合,如下圖所示。
圖像和容器的20%和40%的垂直和水平線(xiàn)對(duì)齊
結(jié)論
object-fit 屬性設(shè)計(jì)用于與任何類(lèi)型的替代元素一起工作,如圖像、視頻、iframes 和embeds。如何將像視頻這樣的元素適應(yīng)到定義的區(qū)域(其中一些元素可能被隱藏)可能是一個(gè)值得討論的問(wèn)題,但毫無(wú)疑問(wèn),這里有可行的用例。更好的選擇可能是將iframe的寬度設(shè)置為可用空間的width: 100%,然后使用aspect-ratio屬性來(lái)保持其比例。
更常見(jiàn)的是,有一個(gè)圖像需要適應(yīng)的特定空間,所以 object-fit 對(duì)于允許圖像適應(yīng)該空間而不被扭曲(即使其中一部分必須被隱藏)非常有用。
如何使用CSS的object-fit屬性:
object-fit: contain contain值強(qiáng)制圖像完全適應(yīng)其內(nèi)容框,但不會(huì)扭曲。圖像保持其自然的寬高比,因此不會(huì)填滿(mǎn)其容器:
css Copy code img { width: 100%; height: 100%; object-fit: contain; } 你可能會(huì)認(rèn)為,只需在圖像上設(shè)置height: 100%就可以得到上面的相同結(jié)果。但實(shí)際上并不完全如此,因?yàn)檫@樣會(huì)使圖像定位到左邊,而不是居中,這是object-fit的默認(rèn)設(shè)置。結(jié)合object-position,object-fit為圖像在容器內(nèi)的定位提供了更多的選項(xiàng)。
object-fit: none none屬性允許圖像保持其自然的原始尺寸。只有可以適應(yīng)調(diào)整后的內(nèi)容框的部分才是可見(jiàn)的。
與object-fit: cover不同,我們的圖像不會(huì)被強(qiáng)制在至少一個(gè)軸上完全可見(jiàn)。原始圖像的寬度和高度都大于內(nèi)容框,所以它在兩個(gè)方向上都溢出,如下圖所示。
none值保持圖像的正常大小,因此在容器中看不到圖像的頂部、底部和兩側(cè)。
再次注意,默認(rèn)情況下,圖像的中心與內(nèi)容框的中心對(duì)齊。
還要注意,object-fit: none并不意味著object-fit什么都不做。正如我們所看到的,與完全沒(méi)有object-fit設(shè)置相比,它做了很多工作。(如果你在上面的Pen中刪除object-fit: none,你會(huì)得到一個(gè)提醒。)
object-fit: scale-down scale-down屬性與none或contain相同。它選擇使圖像顯示得更小的那個(gè)。
顯然,在我們當(dāng)前的示例中,它會(huì)選擇contain,因?yàn)槲覀兊娜萜鞅葓D像小。如果我們的容器比圖像大,none會(huì)占主導(dǎo)地位,圖像會(huì)保持其自然大小,而不是在一個(gè)方向上填充容器,如你在這個(gè)CodePen演示中所看到的。
object-fit: fill 如果我們?cè)谘菔局袑bject-fit值更改為fill,就好像根本沒(méi)有設(shè)置object-fit。這是因?yàn)?,默認(rèn)情況下,圖像無(wú)論設(shè)置了什么尺寸都會(huì)填充其內(nèi)容框。
因?yàn)閒ill屬性可能會(huì)扭曲圖像,所以在大多數(shù)情況下,它可能不是最好的選擇。
使用object-fit而不使用容器 在上面的示例中,我們一直在使用object-fit來(lái)調(diào)整div容器內(nèi)的圖像大小,但我們?cè)趯?shí)踐中看到的原理在沒(méi)有容器的情況下同樣適用。重要的是圖像的內(nèi)容框的大小以及圖像在該框內(nèi)的顯示方式。
例如,我們可以將以下CSS應(yīng)用于圖像,而不需要任何周?chē)膁iv:
css Copy code img { width: 300px; height: 300px; object-fit: contain; } 下面的CodePen演示中顯示了結(jié)果。
嘗試更改上面的Pen中object-fit屬性的值為cover、fill、scale-down和none,看看每個(gè)的行為如何。結(jié)果與圖像設(shè)置為寬度和高度為100%并包含在一個(gè)設(shè)置為300px乘300px的div中的結(jié)果相同。
在響應(yīng)式布局中使用object-fit object-fit屬性在圖像的指定區(qū)域的尺寸響應(yīng)瀏覽器視口大小的情況下可能最有用。以下演示將我們的圖像分配給一個(gè)特定的、靈活的網(wǎng)格區(qū)域:
css Copy code img { width: 100%; height: 100%; object-fit: cover; grid-row: 2 / 3; grid-column: 2 / 3; }
article { display: grid; grid-template: 5% 1fr 10% / 40% 1fr 40%; height: 100vh; } 隨著視口和網(wǎng)格區(qū)域的擴(kuò)展和收縮,cover值確保圖像始終很好地適應(yīng)其網(wǎng)格區(qū)域,改變圖像的可見(jiàn)部分,使其永遠(yuǎn)不會(huì)扭曲。(查看全屏視圖的演示以獲得最佳效果。)
要了解更多關(guān)于網(wǎng)格區(qū)域的信息,請(qǐng)查看我們的CSS Grid初學(xué)者指南。
使用object-position設(shè)置圖像的位置 正如background-position用于設(shè)置容器內(nèi)背景圖像的位置一樣,object-position屬性用于控制圖像元素在其自己的內(nèi)容框內(nèi)的位置。
正如我們所看到的,object-position默認(rèn)為50% 50%,這意味著圖像的中心與其內(nèi)容框的中心對(duì)齊。我們可以使用一系列的關(guān)鍵字值(如top、bottom、left、right、center)或使用長(zhǎng)度值(如px、em或%)或兩者的組合來(lái)更改這一點(diǎn)。
假設(shè)我們現(xiàn)在想要從右下角定位我們的圖像。我們可以使用關(guān)鍵字right bottom,或百分比值100% 100%:
css Copy code img { width: 100%; height: 100%; object-fit: cover; object-position: right bottom; /* 或 100% 100% */ } 下面的圖像說(shuō)明了我們的圖像現(xiàn)在的位置。
我們的圖像現(xiàn)在從右下角定位,這樣圖像的頂部部分被隱藏了
你可以在上面的Pen中嘗試定位關(guān)鍵字,看看它們是如何工作的,以及object-fit關(guān)鍵字,但結(jié)果應(yīng)該很容易預(yù)測(cè)。
我們還可以使用像像素或ems這樣的單位偏移圖像從其容器。例如:
css Copy code img { width: 100%; height: 100%; object-fit: cover; object-position: 20px 2em; /* 從左邊20px和從頂部2em */ } 我們可以通過(guò)結(jié)合單位和關(guān)鍵字來(lái)從右下角進(jìn)行類(lèi)似的偏移,如下所示:
css Copy code img { width: 100%; height: 100%; object-fit: cover; object-position: right 20px bottom 2em; /* 從右邊20px和從底部2em */ } 我們已經(jīng)看到,我們可以使用百分比來(lái)定位圖像在其內(nèi)容框中。與background-position屬性一樣,使用百分比與object-position可能會(huì)有點(diǎn)混淆。object-position為50% 50%意味著圖像的中心與其內(nèi)容框的中心在水平和垂直軸上對(duì)齊。
如果我們將object-position設(shè)置為20% 40%,這意味著圖像左邊20%的垂直線(xiàn)與內(nèi)容框左邊20%的垂直線(xiàn)重合,圖像頂部40%的水平線(xiàn)與內(nèi)容框頂部40%的水平線(xiàn)重合,如下圖所示。
圖像和容器的20%和40%的垂直和水平線(xiàn)對(duì)齊
我們可以在下面的CodePen演示中看到這一點(diǎn)。
結(jié)論 object-fit屬性設(shè)計(jì)用于與任何類(lèi)型的替代元素一起工作,如圖像、視頻、iframes和embeds。如何將像視頻這樣的元素適應(yīng)到定義的區(qū)域(其中一些元素可能被隱藏)可能是一個(gè)值得討論的問(wèn)題,但毫無(wú)疑問(wèn),這里有可行的用例。更好的選擇可能是將iframe的寬度設(shè)置為可用空間的width: 100%,然后使用aspect-ratio屬性來(lái)保持其比例。
更常見(jiàn)的是,有一個(gè)圖像需要適應(yīng)的特定空間,所以object-fit對(duì)于允許圖像適應(yīng)該空間而不被扭曲(即使其中一部分必須被隱藏)非常有用。
最后,正如上面所提到的,值得將 object-fit 和 object-position 屬性與 background-size 和 background-position 屬性進(jìn)行比較,它們有很多相似之處。