web 圖像技術:前端引入圖片的各類方式及其優缺點

做者:ahmad shadeed
譯者:前端小智
來源:developers
點贊再看,養成習慣

本文 GitHub https://github.com/qq44924588... 上已經收錄,更多往期高贊文章的分類,也整理了不少個人文檔,和教程資料。歡迎Star和完善,你們面試能夠參照考點複習,但願咱們一塊兒有點東西。css

前端開發人員在構建網站時須要作的一個決定是引入圖片的方式。它能夠是<img>標籤,或者是經過CSS background 屬性,還可使用 SVG <image>。選擇正確的方式是很重要的,它對性能和可訪問性有很大的影響。html

在本文中,咱們會學習引入圖像的各類方式,以及每種方式的優勢和缺點,以及什麼時候使用和爲何使用它們。前端

HTML <img> 元素

最簡單的狀況下,img元素必須包含src屬性:git

<img src="cool.jpg" alt="">

設置寬度和高度屬性

在頁面加載時,它們會在頁面圖像加載時發生一些佈局變化。爲了不這種狀況,咱們能夠爲它設置widthheight屬性:github

<img src="cool.jpg" width="200" height="100" alt="">

雖然對某些人來講,這可能看起來太過簡單了,但它是有用的。咱們用圖例的方式來理清這個概念:web

圖片描述

咱們看到到右側圖片即便還沒有加載仍保留了空間? 那是由於設置了寬度和高度。面試

經過 CSS 隱藏圖像

圖像能夠用 CSS 隱藏。 可是,它仍將加載在頁面中。 所以,在執行此操做時請當心。若是一個圖像應該被隱藏,那麼它多是出於裝飾的目的。瀏覽器

img {
    display: none;
}

一樣,上面的方法也不能阻止瀏覽器加載圖像,即便它在視覺上是隱藏的。緣由是<img>被認爲是一個被替換的元素,因此咱們沒法控制它所加載的內容。微信

你們都說簡歷沒項目寫,我就幫你們找了一個項目,還附贈【搭建教程】app

可訪問性問題

經過將alt屬性設置爲有意義的描述,用來訪問 HTML 圖像,這對於屏幕閱讀器用戶很是有幫助。

然而,若是一個alt描述是不須要的,請不要刪除它,若是你這樣作,圖像src將被讀出,這對可訪問性很是不利。

不只如此,若是圖像由於某種緣由沒有加載,而且它有一個清晰的alt,它將做爲一個回退顯示。一樣經過圖例來演示一下。

假設咱們有如下圖片:

<img class="food-thumb" width="300" height="200" src="cheescake.jpg">

<img class="food-thumb" width="300" height="200" src="cheescake.jpg" alt="">

src無效,圖片沒有加載時。第一個沒有alt屬性,而第二個是空的alt屬性,下面是它們的視覺效果:

clipboard.png

沒有alt的圖片仍然保留了它的空間,這很混亂,並且不利於訪問。而另外一個alt爲空的圖片,會摺疊起來看起來像一個小點,這裏由於它有邊框。

可是,當alt屬性有值,它看起來是這樣的:

clipboard.png

這不是一個很好的反饋嗎?此外,當圖像源失敗時,能夠向它們添加僞元素。

響應式圖像

clipboard.png

<img>的優勢在於能夠針對特定視口大小將其擴展爲具備多個版本的照片。 咱們有兩種不一樣的方式來生成一組響應式圖像:

1.srcset屬性

<img src="small.jpg" srcset="medium.jpg 500w, large.jpg 800w" alt="">

這很簡單。 對我來講,srcset能夠根據屏幕寬度顯示多個圖像尺寸,這並非一種完美的解決方案。它讓瀏覽器選擇合適的圖像,而咱們對此無能爲力。

2.picture 標籤

<picture>
  <source srcset="large.jpg" media="(min-width: 800px)" />
  <source srcset="medium.jpg" media="(min-width: 500px)" />
  <img src="small.jpg" />
</picture>

另外一種選擇是使用<picture>元素。 我更喜歡這種方式,由於它更容易預測。

事例源碼:https://codepen.io/shadeed/pe...

調整圖像大小

clipboard.png

對於<img>,咱們還可使用的一組很好的特性object-fitobject-position。它們能夠控制<img>的大小和定位,就像CSS背景圖像。

object-fit 值有:fill, contain, cover, none, scale-down。例如:

img {
    object-fit: cover;
    object-position: 50% 50%;
}

CSS背景圖片

使用CSS背景顯示圖像時,它須要一個具備內容或特定寬度或高度的元素。 一般,背景圖像的主要用途應該是用於裝飾目的。

何使用 CSS 背景圖片

首先,咱們須要一個元素

// html
<div class="element">Some content</div>

// css
.element {
    background: url('cool.jpg');
}

多個背景

使用CSS背景圖片的好處是能夠設置多個背景。考慮如下示例:

.element {
    background: url('cool-1.jpg'), url('cool-2.jpg');
}

隱藏圖像

咱們能夠在特定視口中隱藏和顯示圖像,若是未使用CSS設置圖片,則不會下載該圖片。 與使用<img>相比,這是一個額外的好處。

在上面的示例中,咱們有一個背景圖像,僅在視口寬度大於700px時顯示。

可訪問性問題

若是使用不當,背景圖像可能會影響可訪問性。 例如,將其用於文章主題,這對於文章相當重要。

 非開發人員沒法下載

普通人知道,若是要保存圖像,只需單擊鼠標左鍵,而後選擇保存便可。 CSS 背景圖片並不是如此,咱們必須先檢查元素,而後在DevTools中的url中打開連接,而後才能下載隨CSS添加的圖像。

僞元素

能夠將僞元素與CSS背景圖像一塊兒使用,例如在圖像頂部顯示覆蓋圖。 對於<img>這是不可能的,直到咱們爲疊加層添加單獨的元素。

SVG <Image>

SVG被認爲是一種圖像,它最大的功能是在不影響質量的狀況下進行縮放。此外,使用SVG,咱們能夠嵌入JPGPNGSVG圖像。參見下面的 HTML:

<svg width="200" height="200">
  <image href="cheesecake.jpg" height="100%" width="100%" preserveAspectRatio="xMidYMid slice" />
</svg>

clipboard.png

你是否注意到了prepareAspectRatio? 它的做用是可讓圖像佔據SVG的整個寬度和高度,而不會被拉伸或壓縮。

<image>寬度較大時,它將填充其父級(SVG)寬度而不會拉伸。

clipboard.png

這很是相似於 CSS 中的object-fit: coverbackground-size: cover

可訪問性問題

關於SVG 的可訪問性,這使我想起了<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>

非開發人員沒法下載

必須先檢查元素並複製圖像的URL,而後才能下載嵌入SVG的圖像。 可是,若是咱們要防止用戶下載特定的圖像,這多是一件好事。

用例

Hero Section

在構建hero section時,有時咱們須要在標題和其餘內容下方的圖像。 參見下圖:

clipboard.png

一些要求:

  • 背景圖片可以動態替換
  • 圖片有一個覆蓋層,讓閱讀更容易
  • 圖像有三種尺寸:小號、中號和大號。每個都是針對一個特定的視口。

在開始解決方案以前,讓咱們先問問本身這種背景的性質。 這是一些入門問題:

  1. 爲用戶保留這個圖像很重要嗎,仍是能夠跳過它?
  2. 咱們是否須要在全部視口尺寸上使用它?
  3. 它是靜態的仍是動態變化的?

解決方案1

經過使用多個CSS背景,咱們能夠將一個背景做爲疊加層,將另外一個背景做爲實際圖像。 請看下面的CSS:

.hero {
    background-image: linear-gradient(rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.4)), var('landscape.jpg');
    background-repeat: no-repeat;
    background-size: 100%, cover;
}

雖然此解決方案有效,但可使用 JavaScript 動態更改背景圖片。 見下面:

<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>

這裏添加了一個內聯樣式。雖然這是可行的,但它看起來很醜,並且不實用。

也許咱們可使用CSS變量? 讓咱們來探索一下。

<section class="hero" style="--bg-url: url('landscape.jpg')">
  <!-- Hero content -->
</section>

clipboard.png

如今,咱們能夠輕鬆地更新--bg-url變量來動態更改背, 這比內聯的東西好一百萬倍。

小結:

  1. 這種方案只有在圖片不重要才適用
  2. 這種方案只適合一些靜態網站,由於沒有從後臺拉取圖片

事例源碼:https://codepen.io/shadeed/pe...

你們都說簡歷沒項目寫,我就幫你們找了一個項目,還附贈【搭建教程】

解決方案2

該方案是可使用一個 img 標籤:

<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中,咱們須要將圖片絕對定位在內容下方,而且還須要使用僞元素做爲疊加層。

.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);
}

此解決方案的優勢在於,能夠輕鬆更改圖片的src屬性。 一樣,若是圖像很重要,它將會更加有用。

另外,我喜歡使用HTML <img>的功能是可以在未加載圖片的狀況下添加回退。 回退至少可使內容保持可讀性。

.hero img {
    /* Other styles */
    background: #2962ff;
  }

clipboard.png

在圖片源路徑不對時,背景顏色是一個代替方面。

事例源碼:https://codepen.io/shadeed/pe...

網站 Logo

網站 Logo是很重要的,由於它能夠將網站與其餘網站區分開。 要嵌入徽標,咱們有一些選擇:

* <img> -> png,jpg, orsvg

  • 內聯SVG
  • 背景圖

接下來,咱們來看看哪一種方式更合適。

帶有不少細節的 Logo

當徽標具備許多細節或形狀時,將其用做嵌入式SVG可能沒有好處。 我建議使用<img>,圖像類型能夠是pngjpgsvg

clipboard.png

須要動畫的簡單 Logo

clipboard.png

咱們有一個簡單的logo ,其中包含形狀和文字。 懸停時,形狀和文本須要更改顏色。 怎麼作? 對我來講最好的解決方案是使用嵌入式SVG。

HTML

<a href="#">
    <svg class="logo" width="115" height="47" xmlns="http://www.w3.org/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>

CSS

.logo rect,
.logo text {
  transition: 0.3s ease-out;
}

.logo:hover rect,
.logo:hover text {
  fill: #4a7def;
}

事例源碼:https://codepen.io/shadeed/pe...

響應 Logo

這讓我想起了Smashing Magazine的logo。 我喜歡它從一個小圖標變成一個完整的徽標。 參見下面的模型:

clipboard.png

完美的解決方案是使用<picture>元素,能夠在其中添 加logo 的兩個版本。 以下所示:

<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;
  }
}

這是簡單而直接的解決方案。

事例源碼:https://codepen.io/shadeed/pe...

帶有漸變的Logo

clipboard.png

當 logo 具備漸變時,從IllustratorSketch等設計應用程序將其導出的過程可能並不完美,有時會中斷。

使用SVG,咱們能夠輕鬆地爲logo添加漸變。 我添加了<linearGradient>並將其用做文本填充。

<svg class="logo" width="115" height="47" xmlns="http://www.w3.org/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>

事例源碼:https://codepen.io/shadeed/pe...

用戶頭像

對於用戶頭像,它們具備不少形狀,但最多見的是矩形或圓形。 在此用例中,會介紹一個對你有用的重要技巧。

首先,讓咱們看下面的模型。 請注意,咱們有一個完美的化身,而且100%清晰。

clipboard.png

可是,當用戶上傳半白色頭像或很是淺的頭像時,這個設計就不太好了。

請注意,在上面的模型中,除非真正專一看,不然尚不清楚其中是否有一個圓圈。 這是一個問題。 爲了解決這個問題,咱們應該在頭像內添加邊框,以防圖像太亮看不清除。

clipboard.png

咱們有幾個選擇

  • <img>元素
  • <img><div> 元素
  • <div>與CSS背景
  • SVG <image>

哪個最好? 咱們來探索探索。

使用 HTML <img>

你可能首先想到的是添加一個邊框,對吧?讓咱們來探討一下這個問題。

.avatar {
    border: 2px solid #f2f2f2;
}

clipboard.png

咱們的目標是使內部邊框與圖像融合在一塊兒,這種不太實用。

使用 <img><div> 元素

如今的問題是,要添加內部邊框,咱們不能使用box-shadow,由於它沒法在圖像上使用。 解決方案用<div>包裹 頭像中,並添加專用於內部邊框的元素。

HTML

<div class="avatar-wrapper">
     <img class="avatar" src="shadeed2.jpg" alt="A photo of Ahmad Shadeed">
     <div class="avatar-border"></div>
</div>

CSS

.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);
}

經過在<div>上使用透明度10%黑色的邊框,咱們能夠確保邊框與深色圖像融合,而且只有在圖像較亮的狀況下才可見。 參見下面的模型:

clipboard.png

事例地址:https://codepen.io/shadeed/pe...

使用<div>與CSS背景

若是我要使用<div>來顯示頭像,則可能表示該圖像具備裝飾性。 我記得一個用例,它是分散在頁面中的隨機頭像。

clipboard.png
]

HTML

<div class="avatar" style="--img-url: url(shadeed2.jpg)"></div>

CSS

.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);
}

事例地址:https://codepen.io/shadeed/pe...

使用 SVG <image>

對我來講,這是最有趣的解決方案。 我在檢查Facebook的新設計時注意到了它。

<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>

先對其進行剖析,它包含如下內容:

  • 用於將圖像剪切爲圓形(circle )的蒙版(mask )
  • 對其應用了蒙版的組
  • image自己帶有preserveAspectRatio =「 xMidYMid」
  • 用於內邊界的圓
circle {
  stroke-width: 2;
  stroke: rgba(0, 0, 0, 0.1);
  fill: none;
}

事例地址:https://codepen.io/shadeed/pe...


代碼部署後可能存在的BUG無法實時知道,過後爲了解決這些BUG,花了大量的時間進行log 調試,這邊順便給你們推薦一個好用的BUG監控工具 Fundebug

原文:https://developers.google.com...


交流

文章每週持續更新,能夠微信搜索「 大遷世界 」第一時間閱讀和催更(比博客早一到兩篇喲),本文 GitHub https://github.com/qq449245884/xiaozhi 已經收錄,整理了不少個人文檔,歡迎Star和完善,你們面試能夠參照考點複習,另外關注公衆號,後臺回覆福利,便可看到福利,你懂的。

相關文章
相關標籤/搜索