縮放 SVG 背景

鑑於 SVG 影像的靈活性,當使用 background-image 屬性將其用作背景影像時,需要考慮很多問題,而當使用 background-size 屬性對其進行縮放時,需要考慮的問題就更多了。本文將介紹在使用這些屬性時,SVG 影像的縮放是如何處理的。

背景尺寸調整演算法

用於確定背景影像尺寸的演算法,在很大程度上可以用以下四條規則來概括。有一些邊緣情況未被這些規則覆蓋,但這已經涵蓋了大多數情況。

  1. 如果 background-size 指定了一個固定的尺寸(即百分比和相對單位由其上下文確定),則該尺寸優先。
  2. 如果影像具有固有比例(intrinsic ratio)(即其寬高比是固定的,如 16:9、4:3、2.39:1、1:1 等),則渲染尺寸會保持該比例。
  3. 如果影像指定了尺寸,且該尺寸未被 constraincover 修改,則指定的尺寸優先。
  4. 如果以上情況均不滿足,則影像將以與背景區域相同的尺寸進行渲染。

值得注意的是,背景尺寸調整演算法只關心影像的尺寸和比例,或者說它們是否存在。一個具有固定尺寸的 SVG 影像將被視為與同尺寸的光柵影像一樣。

備註: 如果你嘗試用 CSS 將 SVG 拉伸到不同的寬高比——例如為了將其拉伸以覆蓋整個頁面背景——請確保你的 SVG 包含 preserveAspectRatio="none"。瞭解更多關於 preserveAspectRatio 的資訊。

源影像示例

在深入研究使用不同型別的 SVG 源影像並觀察它們與 background-size 結合使用的效果之前,先看幾個具有不同尺寸和大小設定的源影像示例會很有幫助,我們稍後將在示例中將它們用作 background-image 的值。瀏覽器預設將 <svg> 影像渲染為 300px 寬和 150px 高。

無尺寸和無比例

這個 SVG 漸變影像既沒有尺寸也沒有比例。它不關心自身的大小,也不關心是否保持特定的寬高比。這可以作為一個很好的漸變桌面背景,無論你的螢幕尺寸和寬高比如何都能正常工作。

html
<svg>
  <title>Corner-to-corner gradient</title>
  <defs>
    <linearGradient id="g" x1="0%" x2="100%" y1="0%" y2="100%">
      <stop stop-color="pink" offset="0" />
      <stop stop-color="goldenrod" offset="1" />
    </linearGradient>
  </defs>
  <rect fill="url('#g')" width="100%" height="100%" />
</svg>

指定了一個維度且無比例

這個影像指定了 100 畫素的寬度,但沒有指定高度或固有比例。這基本上就像一條薄薄的桌布,可以拉伸到整個塊的高度。

html
<svg width="100">
  <title>Vertical gradient, with a fixed width</title>
  <defs>
    <linearGradient id="g" x1="0%" x2="0%" y1="0%" y2="100%">
      <stop stop-color="purple" offset="0" />
      <stop stop-color="lime" offset="1" />
    </linearGradient>
  </defs>
  <rect fill="url('#g')" width="100%" height="100%" />
</svg>

指定了一個維度並有固有比例

這個影像指定了 100 畫素的高度,但沒有指定寬度。它還指定了 3:4 的固有寬高比。這確保了它的寬高比始終為 3:4,除非被有意縮放到不成比例的尺寸(即透過明確指定非該比例的寬度和高度)。

這非常類似於同時指定特定的寬度和高度;因為一旦你有了其中一個維度和比例,另一個維度也就被隱含地確定了。

html
<svg height="100" viewBox="0 0 3 4" preserveAspectRatio="none">
  <title>Vertical gradient, with a fixed height and intrinsic ratio</title>
  <defs>
    <linearGradient id="g" x1="0%" x2="0%" y1="0%" y2="100%">
      <stop stop-color="teal" offset="0" />
      <stop stop-color="orange" offset="1" />
    </linearGradient>
  </defs>
  <rect fill="url('#g')" width="100%" height="100%" />
</svg>

無寬度或高度但有固有比例

這個影像沒有指定寬度或高度;相反,它指定了 1:1 的固有比例。它始終是正方形,並且可以在任何尺寸下使用,例如 32x32、128x128 或 512x512。

html
<svg viewBox="0 0 1 1" preserveAspectRatio="none">
  <title>Intrinsic ratio</title>
  <defs>
    <linearGradient id="g" x1="0%" x2="100%" y1="0%" y2="0%">
      <stop stop-color="navy" offset="0" />
      <stop stop-color="maroon" offset="1" />
    </linearGradient>
  </defs>
  <rect fill="url('#g')" width="100%" height="100%" />
</svg>

縮放示例

現在讓我們看一些例子,看看當我們對這些影像應用不同的縮放時會發生什麼。在下面的每個例子中,外圍的 <div> 元素都是 300 畫素寬和 200 畫素高,並帶有 2 畫素寬的邊框。為確保在這些演示中 SVG 背景影像只顯示一次,我們將 background-repeat 設定為 no-repeat

css
div {
  width: 300px;
  height: 200px;
  background-repeat: no-repeat;
  border: 2px solid black;
}

為兩個維度指定固定長度

如果你使用 background-size 為兩個維度指定固定長度,那麼根據上述規則 1,這些長度將始終被使用。換句話說,無論源影像是否指定了其尺寸和/或寬高比,影像都將被拉伸到你指定的尺寸。

無尺寸或固有比例

在此示例中,影像未設定尺寸或固有比例。

css
div {
  background-image: url("no-dimensions-or-ratio.svg");
  background-size: 125px 175px;
}

指定了一個維度,無固有比例

在此示例中,影像指定了一個維度,但未設定固有比例。

css
div {
  background-image: url("100px-wide-no-height-or-ratio.svg");
  background-size: 250px 150px;
}

指定了一個維度並有固有比例

在此示例中,影像明確設定了一個維度,並附帶了固有比例,這意味著兩個維度都得到了有效定義。為 background-size 設定絕對的高度和寬度會覆蓋 SVG 中設定的尺寸。

css
div {
  background-image: url("100px-height-3x4-ratio.svg");
  background-size: 275px 125px;
}

未指定寬度或高度,但有固有比例

在此示例中,影像具有固有比例但未設定尺寸。

css
div {
  background-image: url("no-dimensions-1x1-ratio.svg");
  background-size: 250px 100px;
}

使用 contain 或 cover

background-size 指定 cover 會使圖片在完全覆蓋整個背景區域的同時儘可能小。而 contain 則會使圖片在不被背景區域裁剪的情況下儘可能大。

對於具有固有比例的影像,僅憑 cover/fit 條件就能精確匹配一個尺寸。但如果沒有指定固有比例,cover/fit 就不夠了,因此最終尺寸由最大/最小約束來決定。

無尺寸或固有比例

在此示例中,影像未設定尺寸或固有比例。如果影像既未指定尺寸也未指定固有比例,則規則 2 和規則 3 都不適用,因此規則 4 生效:背景影像被渲染以覆蓋整個背景區域。這滿足了最大或最小的約束條件。

css
div {
  background-image: url("no-dimensions-or-ratio.svg");
  background-size: contain;
}

指定了一個維度,無固有比例

在此示例中,影像指定了一個維度但沒有固有比例,規則 4 適用,影像被縮放以覆蓋整個背景區域。

css
div {
  background-image: url("100px-wide-no-height-or-ratio.svg");
  background-size: contain;
}

指定了一個維度並有固有比例

在這些示例中,影像明確設定了一個維度,並附帶了固有比例。

當你指定一個固有比例時,情況就變了。在這種情況下,規則 1 不相關,所以應用規則 2:我們嘗試保持任何固有比例(同時遵循 containcover)。例如,在一個 300x200 的框中使用 contain 並保持 3:4 的固有寬高比,意味著繪製一個 150x200 的背景。

contain 的情況

給定此 CSS

css
div {
  background-image: url("100px-height-3x4-ratio.svg");
  background-size: contain;
}

請注意整個影像是如何被渲染的,它儘可能地適應框內,而沒有任何部分被裁剪掉。

cover 的情況
css
div {
  background-image: url("100px-height-3x4-ratio.svg");
  background-size: cover;
}

在這裡,3:4 的比例被保持,同時影像被拉伸以填充整個框。這導致影像的底部被裁剪掉了。

無尺寸但有固有比例

這些示例使用設定了固有比例但沒有定義尺寸的影像。當使用沒有固有尺寸但有固有比例的影像時,工作方式類似。

contain 的情況
css
div {
  background-image: url("no-dimensions-1x1-ratio.svg");
  background-size: contain;
}

請注意,影像的大小被調整以適應最小的維度,同時保持 1:1 的寬高比。

cover 的情況
css
div {
  background-image: url("no-dimensions-1x1-ratio.svg");
  background-size: cover;
}

在這裡,影像的大小被調整以填充最大的維度。1:1 的寬高比得以保持,儘管對於這個源影像來說,這一點可能很難看出來。

對兩個維度使用“auto”進行自動調整

如果 background-size 設定為 autoauto auto,規則 2 指出渲染必須保持所提供的任何固有比例。

無尺寸或固有比例

當自動調整未指定固有比例或尺寸的背景影像時,規則 4 生效,影像被渲染以填充背景區域。

css
div {
  background-image: url("no-dimensions-or-ratio.svg");
  background-size: auto auto;
}

一個維度且無固有比例

如果沒有指定固有比例,但至少指定了一個維度,則規則 3 生效,我們根據這些維度來渲染影像。

css
div {
  background-image: url("100px-wide-no-height-or-ratio.svg");
  background-size: auto auto;
}

請注意,源 SVG 中指定的 100 畫素寬度得到了遵守,而高度則填充了背景區域,因為它未被指定(無論是顯式指定還是透過固有比例)。

一個維度和一個固有比例

如果我們有一個固有比例和一個固定的維度,這就固定了兩個維度。如前所述,知道一個維度和一個比例等同於明確指定兩個維度。

css
div {
  background-image: url("100px-height-3x4-ratio.svg");
  background-size: auto auto;
}

由於此影像的顯式高度為 100px。在 SVG 中設定了 3:4 的比例,在 auto 的情況下,影像的寬度為 75 畫素。

無固定尺寸但有固有比例

當指定了固有比例但沒有指定尺寸時,應用規則 4——除了規則 2 也適用。因此,影像的渲染方式與 contain 的情況相同。

css
div {
  background-image: url("no-dimensions-1x1-ratio.svg");
  background-size: auto auto;
}

使用“auto”和一個特定長度

根據規則 1,指定的尺寸總是被使用,所以我們只需要用我們的規則來確定第二個維度。

無尺寸或固有比例

如果影像沒有尺寸或固有比例,則應用規則 4,我們使用背景區域的維度來確定 auto 維度的值。

css
div {
  background-image: url("no-dimensions-or-ratio.svg");
  background-size: auto 140px;
}

在這裡,寬度根據規則 4 使用背景區域的寬度來確定,而高度是 CSS 中指定的 140px

指定了一個維度但無固有比例

如果影像指定了一個維度但沒有固有比例,並且該維度在 CSS 中設定為 auto,則根據規則 3 使用該指定維度。

css
div {
  background-image: url("100px-wide-no-height-or-ratio.svg");
  background-size: 200px auto;
}

在這裡,根據規則 1,CSS 中指定的 200px 覆蓋了 SVG 中指定的 100px 寬度。由於沒有提供固有比例或高度,auto 會選擇背景區域的高度作為渲染影像的高度。

css
div {
  background-image: url("100px-wide-no-height-or-ratio.svg");
  background-size: auto 125px;
}

在這種情況下,寬度在 CSS 中被指定為 auto,因此根據規則 3,選擇 SVG 中指定的 100px 寬度。高度在 CSS 中設定為 125px,因此根據規則 1 選擇該值。

指定了一個維度並有固有比例

當指定了一個維度時,規則 1 會將 SVG 中的該維度應用於渲染的背景,除非被 CSS 特別覆蓋。當也指定了固有比例時,該比例用於確定另一個維度。

css
div {
  background-image: url("100px-height-3x4-ratio.svg");
  background-size: 150px auto;
}

在這種情況下,我們使用 CSS 中設定的 150px 影像寬度,所以應用規則 1。然後,固有的 3:4 寬高比決定了 auto 情況下的高度。

未指定尺寸但有固有比例

如果在 SVG 中沒有指定尺寸,則應用 CSS 中指定的尺寸,然後根據規則 2 使用固有比例來選擇另一個維度。

css
div {
  background-image: url("no-dimensions-1x1-ratio.svg");
  background-size: 150px auto;
}

寬度由 CSS 設定為 150px。高度的 auto 值是使用該寬度和 1:1 的寬高比計算得出的,結果也是 150px

另見