譯者:飄飄 作者:Ahmad https:///article/image-techniques/
前端開(kāi)發(fā)者在構(gòu)建網(wǎng)站時(shí)需要做的一個(gè)決定是添加圖片的技術(shù)。它可以是一個(gè)HTML <img> ,或者是通過(guò)CSS背景生成的圖片,也可能是SVG <image> 。選擇正確的技術(shù)很重要,對(duì)網(wǎng)站的性能和可訪問(wèn)性起著巨大的作用。 在這篇文章中,我們將學(xué)習(xí)各種圖片添加方式,以及每種方式的優(yōu)缺點(diǎn),以及什么時(shí)候和為什么要使用每種方式的上下文。 HTML <Img> 元素在最簡(jiǎn)單的情況下,image元素必須根據(jù)需要包含src屬性。 <img src='cool.jpg' alt=''>
設(shè)置寬高屬性在頁(yè)面加載時(shí),它們會(huì)在頁(yè)面的圖片加載過(guò)程中出現(xiàn)一些布局移動(dòng)。為了避免這種情況,我們可以為它設(shè)置寬度和高度屬性。 雖然這對(duì)有些人來(lái)說(shuō)可能看起來(lái)有點(diǎn)老套,但還是很有用的。讓我們來(lái)直觀地理解一下這個(gè)概念。
你注意到了嗎,右邊的圖片即使還沒(méi)有加載,也會(huì)保留空間嗎?這是因?yàn)閷挾群透叨纫呀?jīng)設(shè)置好了。它有明顯的區(qū)別!
Demo:https:///shadeed/pen/a42ab701809acfecdd4d8f472bb6c043?editors=0100 用CSS隱藏圖片一張圖片可以用CSS隱藏起來(lái)。但是,它仍然會(huì)被加載到頁(yè)面中。因此,在做的時(shí)候請(qǐng)注意。如果一個(gè)圖片應(yīng)該被隱藏,那么可能是為了裝飾目的。 img {
display: none;
}
還是那句話,上面的內(nèi)容不會(huì)阻止瀏覽器加載圖片,即使它在視覺(jué)上是隱藏的。原因是 <img> 被認(rèn)為是被替換的元素,所以我們無(wú)法控制它加載的內(nèi)容。 可訪問(wèn)性問(wèn)題HTML圖片應(yīng)該通過(guò)將alt屬性設(shè)置為有意義的描述來(lái)訪問(wèn)。這對(duì)屏幕閱讀器用戶來(lái)說(shuō)是非常有幫助的。 但是,如果不需要alt描述,請(qǐng)不要?jiǎng)h除,如果刪除了,圖片的src就會(huì)被讀出! 這對(duì)可訪問(wèn)性是非常不利的。 不僅如此,如果圖片因?yàn)槟承┰驔](méi)有加載,而它有一個(gè)明確的alt說(shuō)明,那么它將會(huì)作為一個(gè)回退顯示。既然有一些有趣的事情我想讓大家知道,那我們就從視覺(jué)上說(shuō)說(shuō)吧。 我們有以下的圖片。 <img class='food-thumb' width='300' height='200' src='cheescake.jpg'>
<img class='food-thumb' width='300' height='200' src='cheescake.jpg' alt=''>
src是無(wú)效的,沒(méi)有加載。前者沒(méi)有alt屬性,而后者有一個(gè)空的alt。你能期待這樣的視覺(jué)效果嗎? 沒(méi)有alt的圖片仍然保留了它的空間,這讓人感到困惑,也不利于訪問(wèn)。而另一張折疊起來(lái),以適應(yīng)其空的alt屬性的內(nèi)容,這就造成了它因?yàn)橛羞吙蚨@得很細(xì)小。 但是,當(dāng)有了alt屬性值后,它就會(huì)變成這樣的樣子。 這不是很好的反饋嗎?另外,當(dāng)圖片源失敗時(shí),可以給它們添加偽元素。 響應(yīng)式圖片<img> 的好處是,它可以擴(kuò)展為具有特定視口大小的照片的多個(gè)版本。比如說(shuō),這可以用于文章圖片。
我們有兩種不同的方式獲得一組響應(yīng)式的圖片集。 srcset屬性<img src='small.jpg' srcset='medium.jpg 500w, large.jpg 800w' alt=''>
這是一個(gè)簡(jiǎn)單的問(wèn)題。對(duì)于我來(lái)說(shuō),我認(rèn)為使用 srcset并不是一個(gè)完美的解決方案,根據(jù)屏幕寬度的不同,出現(xiàn)多個(gè)圖片的大小。這個(gè)選擇只能由瀏覽器來(lái)挑選合適的圖片,而我們并沒(méi)有控制權(quán)。 HTML Picture 元素
<picture>
<source srcset='large.jpg' media='(min-width: 800px)' />
<source srcset='medium.jpg' media='(min-width: 500px)' />
<img src='small.jpg' />
</picture>
另一個(gè)選擇是使用 <picture> 元素。我更喜歡這個(gè),因?yàn)樗菀缀透深A(yù)測(cè)。 demo:https:///shadeed/pen/d703aee137f38c138f2323a0252548ac?editors=1100 調(diào)整圖片的大小我們可以使用 <img> 的一個(gè)偉大的東西就是object-fit和object-position屬性。它們讓我們可以控制 <img> 的內(nèi)容如何調(diào)整大小和位置,就像CSS背景圖片一樣。 object-fit的可能值有:fill, contain, cover, none, scale-down
它可以這樣使用。 img {
object-fit: cover;
object-position: 50% 50%;
}
現(xiàn)在我們已經(jīng)對(duì) <img> 元素做了一個(gè)介紹,現(xiàn)在是時(shí)候繼續(xù)前進(jìn),探索第二個(gè)技巧了。 CSS背景圖片當(dāng)使用CSS背景來(lái)顯示圖片時(shí),需要一個(gè)有內(nèi)容或特定寬度或高度的元素。通常情況下,背景圖片的主要用途應(yīng)該是用于裝飾。 如何使用CSS背景圖片很簡(jiǎn)單,我們需要一個(gè)元素。 <div class='element'>Some content</div>
.element {
background: url('cool.jpg');
}
多重背景使用CSS背景圖片的好處是有多個(gè)背景,可以用CSS輕松控制??紤]一下下面的例子。 .element {
background: url('cool-1.jpg'), url('cool-2.jpg');
}
隱藏圖像我們可以在特定視口中隱藏和顯示圖像,而無(wú)需下載它。如果未使用CSS設(shè)置圖片,則不會(huì)下載該圖片。與使用 <img> 相比,這是一個(gè)額外的好處。 @media (min-width: 700px) {
.element {
background: url('cool-1.jpg');
}
}
在上面的例子中,我們有一個(gè)背景圖片,只有當(dāng)視口寬度大于700px時(shí)才會(huì)顯示。 可訪問(wèn)性問(wèn)題如果使用不正確,背景圖片可能會(huì)影響可訪問(wèn)性。例如,將其用于文章中的大拇指,這對(duì)文章至關(guān)重要。 非開(kāi)發(fā)人員用戶不能下載你可能會(huì)覺(jué)得好笑,但正常人都知道,如果你想保存一張圖片,只需點(diǎn)擊右鍵,然后選擇保存即可。而CSS背景圖片卻不是這樣的。在檢查該元素時(shí),要先檢查該元素,然后在DevTools中打開(kāi)URL里面的鏈接,才可以下載一個(gè)正在添加CSS的圖片。 偽元素可以使用偽元素與CSS背景圖片一起使用,例如,在圖片的頂部顯示一個(gè)疊加元素。對(duì)于 <img> ,除非我們?yōu)楦采w層添加一個(gè)單獨(dú)的元素,否則無(wú)法做到這一點(diǎn)。 SVG SVG被認(rèn)為是一種圖像,它最大的功能是在不影響質(zhì)量的前提下進(jìn)行縮放。此外,在SVG中,我們可以嵌入JPG、PNG或SVG圖像。請(qǐng)看下面的HTML。 <svg width='200' height='200'>
<image href='cheesecake.jpg' height='100%' width='100%' preserveAspectRatio='xMidYMid slice' />
</svg>
你有沒(méi)有注意到 preserveAspectRatio?這就是保持SVG全寬和全高的圖像原因,而不被拉伸或壓縮。 當(dāng) <image> 寬度變大時(shí),它將填充其父圖像(SVG)的寬度而不被拉伸。 這與 CSS 中的 object-fit: cover 或 background-size: cover 非常相似。 可訪問(wèn)性關(guān)注的問(wèn)題說(shuō)到SVG的可訪問(wèn)性,這讓我想起了 <title> 元素。例如,我們可以像下面這樣添加它。 <svg width='200' height='200'>
<title>A photo of blueberry Cheescake</title>
<image href='cheesecake.jpg' height='100%' width='100%' preserveAspectRatio='xMidYMid slice' />
</svg>
更多的,我們可以使用 <desc> 元素。 <svg width='200' height='200'>
<title>A photo of blueberry Cheescake</title>
<desc>A meaningful description about the image</desc>
<image href='cheesecake.jpg' height='100%' width='100%' preserveAspectRatio='xMidYMid slice' />
</svg>
非開(kāi)發(fā)者用戶不能下載在檢查SVG元素并復(fù)制圖片的URL之前,無(wú)法下載嵌入到SVG中的圖片。不過(guò),如果我們想阻止用戶下載特定的圖片,這可能是件好事。至少,這樣可以減少用戶輕易下載圖片的幾率。 demo:https:///shadeed/pen/38225ba6b2cd706ca5bff48c131e83ce?editors=1100 用例英雄區(qū)在構(gòu)建英雄欄目時(shí),我們有時(shí)需要在標(biāo)題和其他內(nèi)容的下方設(shè)置一張圖片。請(qǐng)看下圖。 注意,這有一個(gè)圖像。你會(huì)用什么方法來(lái)構(gòu)建呢?那么,之前我先補(bǔ)充一下要求。 在與后臺(tái)CMS整合時(shí),圖片應(yīng)該是動(dòng)態(tài)變化的,很容易就能改變。 在它的上方有一個(gè)疊加,有助于讓內(nèi)容更容易閱讀。 圖片有三種尺寸:小、中、大。每一個(gè)都是針對(duì)特定的視口。
在開(kāi)始解決之前,我們先問(wèn)一下自己這個(gè)背景的性質(zhì)。下面是一些入門(mén)問(wèn)題。 Hero - 解決方案1通過(guò)使用多個(gè)CSS背景,我們可以有一個(gè)用于疊加,另一個(gè)用于實(shí)際圖片。請(qǐng)看下面的CSS。 .hero {
background-image: linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)), url('landscape.jpg');
background-repeat: no-repeat;
background-size: 100%, cover;
}
雖然這個(gè)方案可行,但也可以用JavaScript動(dòng)態(tài)改變背景圖片。請(qǐng)看下面的例子。 <section class='hero' style='background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url('landscape.jpg');'>
<!-- Hero content -->
</section>
我把背景作為內(nèi)嵌式CSS添加了。雖然這樣做可以,但看起來(lái)很難看,也不實(shí)用。 也許我們可以用CSS變量?我們來(lái)探討一下吧。 <section class='hero' style='--bg-url: url('landscape.jpg')'>
<!-- Hero content -->
</section>
現(xiàn)在,我們可以輕松地更新 --bg-url變量,這樣就能動(dòng)態(tài)地改變背景。這比起內(nèi)嵌式的方式要好上百萬(wàn)倍。 解決方案1 經(jīng)驗(yàn)分享demo:https:///shadeed/pen/17978a2d824fd51a3b27c2c2d099a522 英雄 - 解決方案2在這個(gè)解決方案中,我們將使用一個(gè)HTML圖片。請(qǐng)看下面的內(nèi)容。 <section class='hero'>
<h2 class='hero__title'>Using Images in CSS</h2>
<p class='hero__desc'>An article about which and when to use</p>
<img src='landscape.jpg' alt=''>
</section>
在CSS中,我們需要將圖片絕對(duì)定位在內(nèi)容的下方,同時(shí)我們還需要一個(gè)偽元素來(lái)充當(dāng)疊加元素。 .hero {
position: relative;
}
.hero img {
position: absolute;
left: 0;
top: 0;
z-index: -1;
width: 100%;
height: 100%;
object-fit: cover;
}
.hero:after {
content: '';
position: absolute;
left: 0;
top: 0;
z-index: -1;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.4);
}
這個(gè)方案的好處是可以很方便的修改圖片的src屬性。而且,如果圖片是重要的圖片,會(huì)更有用處。 另外,我喜歡使用HTML <img> 的地方是可以在圖片沒(méi)有加載的情況下添加一個(gè)回撤。這個(gè)回撤至少可以保持內(nèi)容的可讀性。 .hero img {
/* Other styles */
background: #2962ff;
}
好在背景只有在源代碼失敗的情況下才會(huì)有效果。這不是很酷嗎? demo:https:///shadeed/pen/73a2ca78141fcab39d6db9d5bd982728?editors=1100 網(wǎng)站標(biāo)志標(biāo)志是一個(gè)網(wǎng)站區(qū)別于其他網(wǎng)站的重要標(biāo)志。要嵌入一個(gè)標(biāo)志,我們有幾個(gè)選項(xiàng)。 <img> : png, jpg, 或svg。
內(nèi)聯(lián)式SVG 背景圖片
下面我們就來(lái)學(xué)習(xí)一下用什么技巧,以及如何選擇合適的技巧。 一個(gè)有很多細(xì)節(jié)的標(biāo)志當(dāng)一個(gè)LOGO有很多細(xì)節(jié)或形狀時(shí),用內(nèi)嵌式SVG可能沒(méi)有那么多好處。我建議使用 <img> ,圖片類型可以是png、jpg或svg。 <a href='#'><img src='logo.svg' alt='Nature Food'></a>
一個(gè)需要?jiǎng)赢?huà)化的簡(jiǎn)單標(biāo)志我們有一個(gè)簡(jiǎn)單的標(biāo)志,它由形狀和文字組成。在懸停時(shí),形狀和文字需要改變顏色。如何做到這一點(diǎn)呢?對(duì)我來(lái)說(shuō),最好的解決方案是使用內(nèi)嵌式SVG。 <a href='#'>
<svg class='logo' width='115' height='47' xmlns='http://www./2000/svg'>
<g transform='translate(-5 -5)' fill='none' fill-rule='evenodd'>
<rect fill='#D8D8D8' transform='rotate(45 28.5 28.5)' x='9' y='9' width='39' height='39' rx='11' />
<text font-family='Rubik-Medium, Rubik' font-size='25' font-weight='400' fill='#6F6F6F'>
<tspan x='63.923' y='36.923'>Rect</tspan>
</text>
</g>
</svg>
</a>
.logo rect,
.logo text {
transition: 0.3s ease-out;
}
.logo:hover rect,
.logo:hover text {
fill: #4a7def;
}
一個(gè)響應(yīng)式的標(biāo)志這讓我想起了Smashing Magazine的標(biāo)志。我喜歡它從一個(gè)小圖標(biāo)變成了一個(gè)完整的標(biāo)志。請(qǐng)看下面的模擬圖。 這方面的完美解決方案是 <picture> 元素,在這里可以添加兩個(gè)版本的標(biāo)志。見(jiàn)下圖。 <a class='logo' href='/'>
<picture>
<source media='(min-width: 1350px)' srcset='sm-logo--full.svg'><img src='sm-logo.svg' alt='Smashing Magazine'></picture>
</a>
而在CSS中,我們需要改變視口寬度等于或大于1350px的寬度。 .logo {
display: inline-block;
width: 45px;
}
@media (min-width: 1350px) {
.logo {
width: 180px;
}
}
簡(jiǎn)單明了的解決方案。 demo:https:///shadeed/pen/6cf55d4e87b7c443820bd5f8694587a8?editors=1100 一個(gè)帶有漸變標(biāo)志當(dāng)有一個(gè)LOGO有了漸變的時(shí)候,從Illustrator或Sketch等設(shè)計(jì)應(yīng)用程序中導(dǎo)出的過(guò)程中,可能會(huì)有不完美的地方,有時(shí)會(huì)出現(xiàn)破損。 有了SVG,我們就可以輕松地給LOGO添加漸變。我添加了一個(gè) <linearGradient> ,并將其作為填充應(yīng)用到文字中。 <svg class='logo' width='115' height='47' xmlns='http://www./2000/svg'>
<defs>
<linearGradient id='gradient' x1='0%' y1='100%' x2='0%' y2='0%'>
<stop offset='0%' stop-color='#4a7def'></stop>
<stop offset='50%' stop-color='#ab4787'></stop>
</linearGradient>
</defs>
<g transform='translate(-5 -5)' fill='none' fill-rule='evenodd'>
<rect fill='#AB4787' transform='rotate(45 28.5 28.5)' x='9' y='9' width='39' height='39' rx='11' />
<text font-family='Rubik-Medium, Rubik' font-size='30' font-weight='400' fill='url(#gradient)'>
<tspan x='63.923' y='36.923'>Rect</tspan>
</text>
</g>
</svg>
用戶頭像對(duì)于一個(gè)用戶頭像來(lái)說(shuō),它們的形狀有很多,但最常見(jiàn)的是長(zhǎng)方形或圓形的頭像。在這個(gè)用例中,我想為大家講解一個(gè)重要的提示,可能會(huì)對(duì)大家有所幫助。 首先,我們來(lái)看看下面的模擬圖。注意,我們有一個(gè)完美的頭像,而且它們是100%的清晰。 但是,當(dāng)用戶上傳的頭像是半白色的,或者是很淡的頭像時(shí),這個(gè)設(shè)計(jì)就會(huì)失敗。 注意到上面的模擬圖中,你要真的聚焦好了才知道里面有一個(gè)圓圈。這就是一個(gè)問(wèn)題。為了解決這個(gè)問(wèn)題,我們應(yīng)該在頭像內(nèi)部添加一個(gè)邊框,這將是在圖像太輕的情況下作為備用。 我們有幾個(gè)選項(xiàng)可以做到這一點(diǎn)。 一個(gè) <img> 元素 一個(gè)帶有 <div> 的 <img> 一個(gè)帶有CSS背景的 <div> SVG <image>
到底哪家好呢?讓我們一起來(lái)探討一下。 使用HTML 大家可能首先想到的是加邊框吧?讓我們一起來(lái)探討一下吧(不好意思,下面的章節(jié)中可能會(huì)經(jīng)??吹轿业谋砬椋?。 .avatar {
border: 2px solid #f2f2f2;
}
我們的目標(biāo)是要有一個(gè)與圖像相融合的內(nèi)部邊框。有實(shí)體邊框并不實(shí)用。 使用HTML <img> 與 <div> 的使用方法現(xiàn)在的問(wèn)題是,要添加一個(gè)內(nèi)邊框,我們不能使用內(nèi)嵌框陰影,因?yàn)樗趫D片上不起作用。解決的辦法是將頭像包裹在 <div> 中,并為內(nèi)邊框添加一個(gè)專用元素。 <div class='avatar-wrapper'>
<img class='avatar' src='shadeed2.jpg' alt='A photo of Ahmad Shadeed'>
<div class='avatar-border'></div>
</div>
.avatar-wrapper {
position: relative;
width: 150px;
height: 150px;
}
.avatar-border {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
border-radius: 50%;
border: 2px solid rgba(0, 0, 0, 0.1);
}
通過(guò)在 <div> 上設(shè)置一個(gè)10%的黑色邊框,我們可以確保邊框與暗色圖像融合,只有在圖像顏色較淺的情況下,邊框才會(huì)顯現(xiàn)出來(lái)。請(qǐng)看下面的模擬圖。 一個(gè)帶有CSS背景的如果我會(huì)用 <div> 來(lái)顯示頭像,那可能意味著頭像是裝飾性的。我想起了一個(gè)用例,那就是散落在頁(yè)面中的隨機(jī)頭像。 我們可以這樣做。 <div class='avatar' style='--img-url: url(shadeed2.jpg)'></div>
.avatar {
background: var(--img-url) center/cover;
width: 150px;
height: 150px;
border-radius: 50%;
box-shadow: inset 0 0 0 2px rgba(#000, 0.1);
}
SVG <image> 這是我最感興趣的解決方案。我在檢查Facebook的新設(shè)計(jì)時(shí)注意到了它。 <svg role='none' style='height: 36px; width: 36px;'>
<mask id='avatar'>
<circle cx='18' cy='18' fill='white' r='18'></circle>
</mask>
<g mask='url(#avatar)'>
<image x='0' y='0' height='100%' preserveAspectRatio='xMidYMid slice' width='100%' xlink:href='avatar.jpg' style='height: 36px; width: 36px;'></image>
<circle cx='18' cy='18' r='18'></circle>
</g>
</svg>
我先來(lái)剖析一下,它包含以下內(nèi)容。 在CSS中,我們將有以下幾點(diǎn)。 circle {
stroke-width: 2;
stroke: rgba(0, 0, 0, 0.1);
fill: none;
}
這就是用戶頭像的使用案例。 有圖標(biāo)的輸入經(jīng)常會(huì)看到有一個(gè)帶圖標(biāo)的輸入框,如何添加?當(dāng)輸入框被聚焦后會(huì)有什么情況呢?我們一起來(lái)探討一下。 <p>
<label for='name'>Full name</label>
<input type='text' id='name'>
</p>
對(duì)我來(lái)說(shuō),處理這種情況的最佳方案是CSS背景圖片。它很簡(jiǎn)單、快速,而且不需要添加更多的元素。 input {
background-color: #fff;
background-image: url('user.svg');
background-size: 20px 20px;
background-position: left 10px center;
background-repeat: no-repeat;
}
而要想改變焦點(diǎn)上的圖標(biāo)顏色,我們可以使用URL編碼的SVG,就可以輕松完成。Yoksel的這個(gè)工具非常棒。 CSS印刷用戶可能需要打印一個(gè)網(wǎng)頁(yè)。比如說(shuō)我們有一個(gè)菜譜,你想把它打印出來(lái),這樣就可以在廚房里看,而不需要檢查手機(jī)或電腦。 對(duì)于一個(gè)包含圖文并茂的菜譜,一定要用打印的方式顯示出來(lái),否則用戶根本無(wú)法從打印網(wǎng)頁(yè)中得到任何好處。 避免使用圖片作為CSS背景當(dāng)一個(gè)圖片作為CSS背景被包含時(shí),它將不會(huì)被打印出來(lái),而是會(huì)出現(xiàn)一個(gè)空位。見(jiàn)下圖。 就是這樣的情況。我們可以通過(guò)強(qiáng)制瀏覽器顯示圖片來(lái)解決這個(gè)問(wèn)題,雖然這對(duì)Firefox和IE來(lái)說(shuō)不起作用。 .element {
background: url('cheesecake.png') center/cover no-repeat;
-webkit-print-color-adjust: exact; /* Force the browser to render the background in print mode */
}
但是,使用HTML <img> 比較安全,因?yàn)樗拇蛴〔粫?huì)有任何問(wèn)題。
|