同個頁面上多個 inline SVG 顯示相互影響,以及 display: none 的顯示問題

Standard

在製作網頁上我們經常選擇 SVG 格式來處理向量圖片的顯示,它擁有清晰、能夠放大縮小、可動態修改等好處。近日工作上同事遇到一個有趣的 SVG 相關 issue,想起剛好我過去也曾經遇過類似的問題,發現之前沒有筆記下來,雖然只是個很小的東西,還是決定整理成文章,方便日後回憶。

情境 1 – 錯置的 linearGradient 定義

假設我們有 2 個不同的漸層 SVG icon,以 inline 的方式放置在同一個網頁上:

<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 593.21 593.21">
  <defs>
    <linearGradient id="a" x1="5686.65" y1="-2326.29" x2="12487" y2="-6979.17" gradientTransform="matrix(.07 0 0 -.07 -357.65 -38.39)" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#ff3b3b"/>
      <stop offset="1" stop-color="#ff9914"/>
    </linearGradient>
  </defs>
  <g data-name="Layer 2">
    <g data-name="Layer 1">
      <g data-name="Layer_1">
        <circle cx="296.6" cy="296.6" r="296.6" style="fill:url(#a)"/>
        <path d="M285.86 107a75.41 75.41 0 0 0-45.34 22.25c-9.09 9-17.7 18.24-26.91 27.33-4.61 4.73-9.27 9.33-13.93 14s-9.8 9.63-14.64 14.53-8.86 9.2-13.34 13.75c-7 7-14 14-21 21.07-5.37 5.55-10.62 11.28-15.93 16.82-3.13 3.31-6.5 6.38-9.45 9.86a83.1 83.1 0 0 0-18.83 52.67c0 1.13 0 2.29.07 3.41A68.86 68.86 0 0 0 115 334.2a119.77 119.77 0 0 0 10.44 16.71c2.6 3.66 4.49 3.6 7.91.77a17 17 0 0 0 1.83-1.77c3.37-3.55 6.67-7.09 10.1-10.63 4.84-5.08 9.8-10.15 14.64-15.29s10.09-10.8 15.17-16.11c2.42-2.6 5-5 7.44-7.56 5.19-5.49 10.27-11.15 15.46-16.58s10.45-10.51 15.53-15.82 11.33-11.81 17.05-17.71 10.57-10.86 15.88-16.29c6.91-7.15 13.64-14.47 20.48-21.61 4.25-4.37 8.62-8.56 12.87-12.87 5.9-5.9 11.39-11.8 17.18-17.7s10.09-9.86 15.05-14.94q16.63-16.8 33.21-33.8a23.64 23.64 0 0 0 2-2.24c2.72-3.43 2.95-4.19-.41-6.61a105.84 105.84 0 0 0-16.41-10.63 77.1 77.1 0 0 0-32.67-7.26h-.56a90.26 90.26 0 0 0-11.28.71l-.06-.06zm97.69 72.66h-.71a33.33 33.33 0 0 0-25.44 11.81 24.63 24.63 0 0 1-1.77 1.77l-18.06 17.71c-5.9 5.91-12.28 12.34-18.48 18.54-5.13 5.13-10.27 10.15-15.34 15.29s-10.51 10.86-16 16.23-11.33 11-17 16.53l-20.13 20.3-37.42 37.43q-24.8 24.9-49.53 49.7c-3.18 3.13-3.24 3.54 0 6.9 7.91 8 15.94 15.94 23.61 24a31.64 31.64 0 0 0 17.83 9.5 42.26 42.26 0 0 0 19.42-.65 29.56 29.56 0 0 0 12.75-6.79l19.6-18.93c4.6-4.42 9.27-8.79 13.81-13.28 9.09-9 18.06-18.06 27.15-27 7.38-7.26 14.94-14.46 22.43-21.72L351 307.05c9.56-9.39 19.18-18.83 28.86-28.22a6.32 6.32 0 0 1 11.14 1.25 43.17 43.17 0 0 1 7.55 24.4 44.26 44.26 0 0 1-.23 4.46A40.72 40.72 0 0 1 388 332.55c-7.09 7.62-14.64 14.82-22 22.14-5.25 5.19-10.62 10.27-15.88 15.52-6.79 6.73-13.46 13.58-20.25 20.31-1 1.12-1.94 2.3-3 3.36l-6.67 6.91c-5 5-10.09 9.86-15 14.87s-10.55 10.87-15.8 16.34c-.47.53-1 .88-1.47 1.35-5.91 5.49-11.34 11-16.95 16.53-2.65 2.6-5.19 5.25-7.79 7.85-4.48 4.55-9.09 9-13.4 13.64-2.65 2.77-2.65 4.48.48 6.67a112.39 112.39 0 0 0 16.35 10.44 82.41 82.41 0 0 0 45.62 6.49 74.59 74.59 0 0 0 41.33-18.83c8.73-7.67 16.53-16.29 24.67-24.55 5.9-5.91 11.81-12.22 18.12-18.3l17.06-17.18c5.2-5.25 10.33-10.51 15.59-15.7s11.8-11.39 17.7-17.24 11.81-11.8 17.71-18.06a136.64 136.64 0 0 0 13-15.35 83.71 83.71 0 0 0 13.41-37.12 82.31 82.31 0 0 0 0-19.84 82.94 82.94 0 0 0-12.46-32.88 95.35 95.35 0 0 0-16.52-19c-16.35-16.23-32.65-32.58-48.64-49.17a37.19 37.19 0 0 0-27.65-12.34h-.22l-1.77.24z" style="fill:#fff;fill-rule:evenodd"/>
      </g>
    </g>
  </g>
</svg>

<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 2000.04 1887.97">
  <defs>
    <linearGradient id="a" y1="-330.01" x2="2000.04" y2="-330.01" gradientTransform="translate(0 1274)" gradientUnits="userSpaceOnUse">
      <stop offset="0" stop-color="#9d4abe"/>
      <stop offset=".03" stop-color="#9055c4"/>
      <stop offset=".15" stop-color="#6b74d6"/>
      <stop offset=".26" stop-color="#4c8fe5"/>
      <stop offset=".39" stop-color="#34a3f0"/>
      <stop offset=".52" stop-color="#22b2f9"/>
      <stop offset=".66" stop-color="#18bafd"/>
      <stop offset=".83" stop-color="#15bdff"/>
      <stop offset="1" stop-color="#28bad5"/>
    </linearGradient>
    <style>
      .cls-2{fill:#fff;opacity:.1;isolation:isolate}
    </style>
  </defs>
  <g id="Layer_2" data-name="Layer 2">
    <g id="Layer_1-2" data-name="Layer 1">
      <path d="M859.79 1803 4.39 60.7C-9.51 32.9 11.39 0 42.19 0h296.4c15.9 0 30.8 9 37.8 22.9l624.7 1264c55.7 113.4 216.8 113.4 272.5 0l622.7-1263c7-13.9 21.9-22.9 37.8-22.9h36.8c21.9 0 35.8 22.9 25.9 41.8L1132.39 1803c-55.7 113.3-216.9 113.3-272.6 0z" style="fill:url(#a)"/>
      <path class="cls-2" d="M859.79 1803 376.39 23.9C369.39 9 353.49 1 340.59 1H43.19c-32.8 0-51.7 32.8-38.8 60.7z"/>
      <path class="cls-2" d="M1001.09 1287.8 4.39 60.7C-7.51 31.9 10.39 3 38.19 0h301.4c16.9 1 29.8 11.9 35.8 22.9z"/>
    </g>
  </g>
</svg>

<!-- SVG Source from https://cryptologos.cc -->

我們期望看到的是:

image

但實際上卻變成了:

image

第二個 icon 的漸層色顯示錯誤,變得像是第一個 icon 的漸層定義。

解決方式也不難,稍微仔細看一下 svg 標籤內容結構的話,可以發現兩個 icon 中 defslinearGradientid 都是 a,但第二個 icon 的漸層定義卻沒有正確套用給第二個 icon。那我們將第二個 icon 中的 <linearGradient id="a" 與套用處的 style="fill:url(#a)"a 都改為 b 、區別開來的話,就是符合預期的結果了。


情境 2 – 多個相同的 inline svg icons 與 display: none

情境 2 又更有意思了一些,這次的情境下我們擺放了兩張相同的、帶有漸層的 SVG icon 在同一張網頁上,就像這樣:

image

基於某些原因,必須讓第一個 icon 隱藏(或是想要讓它的父元素 div 隱藏),只讓第二個 icon 繼續顯示,像這樣:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>SVGs</title>
  <style>
    .c1 {
      display: none;
    }
  </style>
</head>
<body>
  <div class="c1">
    <svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 593.21 593.21"><defs><linearGradient id="a" x1="5686.65" y1="-2326.29" x2="12487" y2="-6979.17" gradientTransform="matrix(.07 0 0 -.07 -357.65 -38.39)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ff3b3b"/><stop offset="1" stop-color="#ff9914"/></linearGradient></defs><g data-name="Layer 2"><g data-name="Layer 1"><g data-name="Layer_1"><circle cx="296.6" cy="296.6" r="296.6" style="fill:url(#a)"/><path d="M285.86 107a75.41 75.41 0 0 0-45.34 22.25c-9.09 9-17.7 18.24-26.91 27.33-4.61 4.73-9.27 9.33-13.93 14s-9.8 9.63-14.64 14.53-8.86 9.2-13.34 13.75c-7 7-14 14-21 21.07-5.37 5.55-10.62 11.28-15.93 16.82-3.13 3.31-6.5 6.38-9.45 9.86a83.1 83.1 0 0 0-18.83 52.67c0 1.13 0 2.29.07 3.41A68.86 68.86 0 0 0 115 334.2a119.77 119.77 0 0 0 10.44 16.71c2.6 3.66 4.49 3.6 7.91.77a17 17 0 0 0 1.83-1.77c3.37-3.55 6.67-7.09 10.1-10.63 4.84-5.08 9.8-10.15 14.64-15.29s10.09-10.8 15.17-16.11c2.42-2.6 5-5 7.44-7.56 5.19-5.49 10.27-11.15 15.46-16.58s10.45-10.51 15.53-15.82 11.33-11.81 17.05-17.71 10.57-10.86 15.88-16.29c6.91-7.15 13.64-14.47 20.48-21.61 4.25-4.37 8.62-8.56 12.87-12.87 5.9-5.9 11.39-11.8 17.18-17.7s10.09-9.86 15.05-14.94q16.63-16.8 33.21-33.8a23.64 23.64 0 0 0 2-2.24c2.72-3.43 2.95-4.19-.41-6.61a105.84 105.84 0 0 0-16.41-10.63 77.1 77.1 0 0 0-32.67-7.26h-.56a90.26 90.26 0 0 0-11.28.71l-.06-.06zm97.69 72.66h-.71a33.33 33.33 0 0 0-25.44 11.81 24.63 24.63 0 0 1-1.77 1.77l-18.06 17.71c-5.9 5.91-12.28 12.34-18.48 18.54-5.13 5.13-10.27 10.15-15.34 15.29s-10.51 10.86-16 16.23-11.33 11-17 16.53l-20.13 20.3-37.42 37.43q-24.8 24.9-49.53 49.7c-3.18 3.13-3.24 3.54 0 6.9 7.91 8 15.94 15.94 23.61 24a31.64 31.64 0 0 0 17.83 9.5 42.26 42.26 0 0 0 19.42-.65 29.56 29.56 0 0 0 12.75-6.79l19.6-18.93c4.6-4.42 9.27-8.79 13.81-13.28 9.09-9 18.06-18.06 27.15-27 7.38-7.26 14.94-14.46 22.43-21.72L351 307.05c9.56-9.39 19.18-18.83 28.86-28.22a6.32 6.32 0 0 1 11.14 1.25 43.17 43.17 0 0 1 7.55 24.4 44.26 44.26 0 0 1-.23 4.46A40.72 40.72 0 0 1 388 332.55c-7.09 7.62-14.64 14.82-22 22.14-5.25 5.19-10.62 10.27-15.88 15.52-6.79 6.73-13.46 13.58-20.25 20.31-1 1.12-1.94 2.3-3 3.36l-6.67 6.91c-5 5-10.09 9.86-15 14.87s-10.55 10.87-15.8 16.34c-.47.53-1 .88-1.47 1.35-5.91 5.49-11.34 11-16.95 16.53-2.65 2.6-5.19 5.25-7.79 7.85-4.48 4.55-9.09 9-13.4 13.64-2.65 2.77-2.65 4.48.48 6.67a112.39 112.39 0 0 0 16.35 10.44 82.41 82.41 0 0 0 45.62 6.49 74.59 74.59 0 0 0 41.33-18.83c8.73-7.67 16.53-16.29 24.67-24.55 5.9-5.91 11.81-12.22 18.12-18.3l17.06-17.18c5.2-5.25 10.33-10.51 15.59-15.7s11.8-11.39 17.7-17.24 11.81-11.8 17.71-18.06a136.64 136.64 0 0 0 13-15.35 83.71 83.71 0 0 0 13.41-37.12 82.31 82.31 0 0 0 0-19.84 82.94 82.94 0 0 0-12.46-32.88 95.35 95.35 0 0 0-16.52-19c-16.35-16.23-32.65-32.58-48.64-49.17a37.19 37.19 0 0 0-27.65-12.34h-.22l-1.77.24z" style="fill:#fff;fill-rule:evenodd"/></g></g></g></svg>
  </div>

  <div class="c2">
    <svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 593.21 593.21"><defs><linearGradient id="a" x1="5686.65" y1="-2326.29" x2="12487" y2="-6979.17" gradientTransform="matrix(.07 0 0 -.07 -357.65 -38.39)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ff3b3b"/><stop offset="1" stop-color="#ff9914"/></linearGradient></defs><g data-name="Layer 2"><g data-name="Layer 1"><g data-name="Layer_1"><circle cx="296.6" cy="296.6" r="296.6" style="fill:url(#a)"/><path d="M285.86 107a75.41 75.41 0 0 0-45.34 22.25c-9.09 9-17.7 18.24-26.91 27.33-4.61 4.73-9.27 9.33-13.93 14s-9.8 9.63-14.64 14.53-8.86 9.2-13.34 13.75c-7 7-14 14-21 21.07-5.37 5.55-10.62 11.28-15.93 16.82-3.13 3.31-6.5 6.38-9.45 9.86a83.1 83.1 0 0 0-18.83 52.67c0 1.13 0 2.29.07 3.41A68.86 68.86 0 0 0 115 334.2a119.77 119.77 0 0 0 10.44 16.71c2.6 3.66 4.49 3.6 7.91.77a17 17 0 0 0 1.83-1.77c3.37-3.55 6.67-7.09 10.1-10.63 4.84-5.08 9.8-10.15 14.64-15.29s10.09-10.8 15.17-16.11c2.42-2.6 5-5 7.44-7.56 5.19-5.49 10.27-11.15 15.46-16.58s10.45-10.51 15.53-15.82 11.33-11.81 17.05-17.71 10.57-10.86 15.88-16.29c6.91-7.15 13.64-14.47 20.48-21.61 4.25-4.37 8.62-8.56 12.87-12.87 5.9-5.9 11.39-11.8 17.18-17.7s10.09-9.86 15.05-14.94q16.63-16.8 33.21-33.8a23.64 23.64 0 0 0 2-2.24c2.72-3.43 2.95-4.19-.41-6.61a105.84 105.84 0 0 0-16.41-10.63 77.1 77.1 0 0 0-32.67-7.26h-.56a90.26 90.26 0 0 0-11.28.71l-.06-.06zm97.69 72.66h-.71a33.33 33.33 0 0 0-25.44 11.81 24.63 24.63 0 0 1-1.77 1.77l-18.06 17.71c-5.9 5.91-12.28 12.34-18.48 18.54-5.13 5.13-10.27 10.15-15.34 15.29s-10.51 10.86-16 16.23-11.33 11-17 16.53l-20.13 20.3-37.42 37.43q-24.8 24.9-49.53 49.7c-3.18 3.13-3.24 3.54 0 6.9 7.91 8 15.94 15.94 23.61 24a31.64 31.64 0 0 0 17.83 9.5 42.26 42.26 0 0 0 19.42-.65 29.56 29.56 0 0 0 12.75-6.79l19.6-18.93c4.6-4.42 9.27-8.79 13.81-13.28 9.09-9 18.06-18.06 27.15-27 7.38-7.26 14.94-14.46 22.43-21.72L351 307.05c9.56-9.39 19.18-18.83 28.86-28.22a6.32 6.32 0 0 1 11.14 1.25 43.17 43.17 0 0 1 7.55 24.4 44.26 44.26 0 0 1-.23 4.46A40.72 40.72 0 0 1 388 332.55c-7.09 7.62-14.64 14.82-22 22.14-5.25 5.19-10.62 10.27-15.88 15.52-6.79 6.73-13.46 13.58-20.25 20.31-1 1.12-1.94 2.3-3 3.36l-6.67 6.91c-5 5-10.09 9.86-15 14.87s-10.55 10.87-15.8 16.34c-.47.53-1 .88-1.47 1.35-5.91 5.49-11.34 11-16.95 16.53-2.65 2.6-5.19 5.25-7.79 7.85-4.48 4.55-9.09 9-13.4 13.64-2.65 2.77-2.65 4.48.48 6.67a112.39 112.39 0 0 0 16.35 10.44 82.41 82.41 0 0 0 45.62 6.49 74.59 74.59 0 0 0 41.33-18.83c8.73-7.67 16.53-16.29 24.67-24.55 5.9-5.91 11.81-12.22 18.12-18.3l17.06-17.18c5.2-5.25 10.33-10.51 15.59-15.7s11.8-11.39 17.7-17.24 11.81-11.8 17.71-18.06a136.64 136.64 0 0 0 13-15.35 83.71 83.71 0 0 0 13.41-37.12 82.31 82.31 0 0 0 0-19.84 82.94 82.94 0 0 0-12.46-32.88 95.35 95.35 0 0 0-16.52-19c-16.35-16.23-32.65-32.58-48.64-49.17a37.19 37.19 0 0 0-27.65-12.34h-.22l-1.77.24z" style="fill:#fff;fill-rule:evenodd"/></g></g></g></svg>
  </div>
</body>
</html>

結果又出現了意想不到的情況,怎麼兩個 icon 都消失了?無論是 Chrome 與 Firefox 皆是如此,但 Safari 卻能夠正常顯示。
(註:本文撰寫時的使用瀏覽器為 macOS 上的 Chrome 91.0.4472.77、Firefox 89.0、Safari 14.1.1(15611.2.7.1.6, 15611))

image

(☝️ 這真的是一張圖,只是就真的是一片白)

我們用 inspector 觀察一下,順便加個灰色的背景色,發現第二個 icon 確實存在,只是漸層效果消失了。

image

而且,只有第一個 icon 被隱藏時才會有這個問題,當今天有三個相同的 icon,但我們隱藏第 2 個時,1 跟 3 都還是能正常顯示。

推測是第一個 icon 的父元素的樣式 display: none; 連帶地讓 defs 中的 linearGradient 失效了,這樣讓後面的 icon 無所參照而顯示異常。

可是,如果對這段沒有理解錯誤的話,這跟 SVG 1.1 中定義的描述 似乎不大一樣:

‘linearGradient’ elements are never rendered directly; their only usage is as something that can be referenced using the ‘fill’ and ‘stroke’ properties. The ‘display’ property does not apply to the ‘linearGradient’ element; thus, ‘linearGradient’ elements are not directly rendered even if the ‘display’ property is set to a value other than none, and ‘linearGradient’ elements are available for referencing even when the ‘display’ property on the ‘linearGradient’ element or any of its ancestors is set to none.

當父元素的樣式 display 設為 none 時,應該也還是能夠在 fill 時取用這個定義的。

找到在 chromium bugs 上面,有個存在許久的 issue 可能與這件事相關:https://bugs.chromium.org/p/chromium/issues/detail?id=258029

也許是瀏覽器實作不同,不過解法同情境 1,將個別的 svg 中的 id 設為 unique id 即可避掉這個問題。


情境 3 – 類似情境 2,但把 defs 內容移到空的 svg 中

StackOverflow 中看到也有人這樣解,將 defs 中的定義移到一個空的 svg 中,其他的 svg 再參照其中定義好的 id 取用。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>SVGs</title>
  <style>
    .defs {
      display: none;
    }
    .c1 {
      display: none;
    }
    .c2 {
      margin-top: 0px;
    }
  </style>
</head>
<body>
  <svg>
    <defs>
      <linearGradient id="a" x1="5686.65" y1="-2326.29" x2="12487" y2="-6979.17" gradientTransform="matrix(0.07, 0, 0, -0.07, -357.65, -38.39)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ff3b3b"/><stop offset="1" stop-color="#ff9914"/></linearGradient>
    </defs>
  </svg>

  <div class="c1">
    <svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 593.21 593.21"><defs><linearGradient id="a" x1="5686.65" y1="-2326.29" x2="12487" y2="-6979.17" gradientTransform="matrix(.07 0 0 -.07 -357.65 -38.39)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ff3b3b"/><stop offset="1" stop-color="#ff9914"/></linearGradient></defs><g data-name="Layer 2"><g data-name="Layer 1"><g data-name="Layer_1"><circle cx="296.6" cy="296.6" r="296.6" style="fill:url(#a)"/><path d="M285.86 107a75.41 75.41 0 0 0-45.34 22.25c-9.09 9-17.7 18.24-26.91 27.33-4.61 4.73-9.27 9.33-13.93 14s-9.8 9.63-14.64 14.53-8.86 9.2-13.34 13.75c-7 7-14 14-21 21.07-5.37 5.55-10.62 11.28-15.93 16.82-3.13 3.31-6.5 6.38-9.45 9.86a83.1 83.1 0 0 0-18.83 52.67c0 1.13 0 2.29.07 3.41A68.86 68.86 0 0 0 115 334.2a119.77 119.77 0 0 0 10.44 16.71c2.6 3.66 4.49 3.6 7.91.77a17 17 0 0 0 1.83-1.77c3.37-3.55 6.67-7.09 10.1-10.63 4.84-5.08 9.8-10.15 14.64-15.29s10.09-10.8 15.17-16.11c2.42-2.6 5-5 7.44-7.56 5.19-5.49 10.27-11.15 15.46-16.58s10.45-10.51 15.53-15.82 11.33-11.81 17.05-17.71 10.57-10.86 15.88-16.29c6.91-7.15 13.64-14.47 20.48-21.61 4.25-4.37 8.62-8.56 12.87-12.87 5.9-5.9 11.39-11.8 17.18-17.7s10.09-9.86 15.05-14.94q16.63-16.8 33.21-33.8a23.64 23.64 0 0 0 2-2.24c2.72-3.43 2.95-4.19-.41-6.61a105.84 105.84 0 0 0-16.41-10.63 77.1 77.1 0 0 0-32.67-7.26h-.56a90.26 90.26 0 0 0-11.28.71l-.06-.06zm97.69 72.66h-.71a33.33 33.33 0 0 0-25.44 11.81 24.63 24.63 0 0 1-1.77 1.77l-18.06 17.71c-5.9 5.91-12.28 12.34-18.48 18.54-5.13 5.13-10.27 10.15-15.34 15.29s-10.51 10.86-16 16.23-11.33 11-17 16.53l-20.13 20.3-37.42 37.43q-24.8 24.9-49.53 49.7c-3.18 3.13-3.24 3.54 0 6.9 7.91 8 15.94 15.94 23.61 24a31.64 31.64 0 0 0 17.83 9.5 42.26 42.26 0 0 0 19.42-.65 29.56 29.56 0 0 0 12.75-6.79l19.6-18.93c4.6-4.42 9.27-8.79 13.81-13.28 9.09-9 18.06-18.06 27.15-27 7.38-7.26 14.94-14.46 22.43-21.72L351 307.05c9.56-9.39 19.18-18.83 28.86-28.22a6.32 6.32 0 0 1 11.14 1.25 43.17 43.17 0 0 1 7.55 24.4 44.26 44.26 0 0 1-.23 4.46A40.72 40.72 0 0 1 388 332.55c-7.09 7.62-14.64 14.82-22 22.14-5.25 5.19-10.62 10.27-15.88 15.52-6.79 6.73-13.46 13.58-20.25 20.31-1 1.12-1.94 2.3-3 3.36l-6.67 6.91c-5 5-10.09 9.86-15 14.87s-10.55 10.87-15.8 16.34c-.47.53-1 .88-1.47 1.35-5.91 5.49-11.34 11-16.95 16.53-2.65 2.6-5.19 5.25-7.79 7.85-4.48 4.55-9.09 9-13.4 13.64-2.65 2.77-2.65 4.48.48 6.67a112.39 112.39 0 0 0 16.35 10.44 82.41 82.41 0 0 0 45.62 6.49 74.59 74.59 0 0 0 41.33-18.83c8.73-7.67 16.53-16.29 24.67-24.55 5.9-5.91 11.81-12.22 18.12-18.3l17.06-17.18c5.2-5.25 10.33-10.51 15.59-15.7s11.8-11.39 17.7-17.24 11.81-11.8 17.71-18.06a136.64 136.64 0 0 0 13-15.35 83.71 83.71 0 0 0 13.41-37.12 82.31 82.31 0 0 0 0-19.84 82.94 82.94 0 0 0-12.46-32.88 95.35 95.35 0 0 0-16.52-19c-16.35-16.23-32.65-32.58-48.64-49.17a37.19 37.19 0 0 0-27.65-12.34h-.22l-1.77.24z" style="fill:#fff;fill-rule:evenodd"/></g></g></g></svg>
  </div>

  <div class="c2">
    <svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 593.21 593.21"><defs><linearGradient id="a" x1="5686.65" y1="-2326.29" x2="12487" y2="-6979.17" gradientTransform="matrix(.07 0 0 -.07 -357.65 -38.39)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ff3b3b"/><stop offset="1" stop-color="#ff9914"/></linearGradient></defs><g data-name="Layer 2"><g data-name="Layer 1"><g data-name="Layer_1"><circle cx="296.6" cy="296.6" r="296.6" style="fill:url(#a)"/><path d="M285.86 107a75.41 75.41 0 0 0-45.34 22.25c-9.09 9-17.7 18.24-26.91 27.33-4.61 4.73-9.27 9.33-13.93 14s-9.8 9.63-14.64 14.53-8.86 9.2-13.34 13.75c-7 7-14 14-21 21.07-5.37 5.55-10.62 11.28-15.93 16.82-3.13 3.31-6.5 6.38-9.45 9.86a83.1 83.1 0 0 0-18.83 52.67c0 1.13 0 2.29.07 3.41A68.86 68.86 0 0 0 115 334.2a119.77 119.77 0 0 0 10.44 16.71c2.6 3.66 4.49 3.6 7.91.77a17 17 0 0 0 1.83-1.77c3.37-3.55 6.67-7.09 10.1-10.63 4.84-5.08 9.8-10.15 14.64-15.29s10.09-10.8 15.17-16.11c2.42-2.6 5-5 7.44-7.56 5.19-5.49 10.27-11.15 15.46-16.58s10.45-10.51 15.53-15.82 11.33-11.81 17.05-17.71 10.57-10.86 15.88-16.29c6.91-7.15 13.64-14.47 20.48-21.61 4.25-4.37 8.62-8.56 12.87-12.87 5.9-5.9 11.39-11.8 17.18-17.7s10.09-9.86 15.05-14.94q16.63-16.8 33.21-33.8a23.64 23.64 0 0 0 2-2.24c2.72-3.43 2.95-4.19-.41-6.61a105.84 105.84 0 0 0-16.41-10.63 77.1 77.1 0 0 0-32.67-7.26h-.56a90.26 90.26 0 0 0-11.28.71l-.06-.06zm97.69 72.66h-.71a33.33 33.33 0 0 0-25.44 11.81 24.63 24.63 0 0 1-1.77 1.77l-18.06 17.71c-5.9 5.91-12.28 12.34-18.48 18.54-5.13 5.13-10.27 10.15-15.34 15.29s-10.51 10.86-16 16.23-11.33 11-17 16.53l-20.13 20.3-37.42 37.43q-24.8 24.9-49.53 49.7c-3.18 3.13-3.24 3.54 0 6.9 7.91 8 15.94 15.94 23.61 24a31.64 31.64 0 0 0 17.83 9.5 42.26 42.26 0 0 0 19.42-.65 29.56 29.56 0 0 0 12.75-6.79l19.6-18.93c4.6-4.42 9.27-8.79 13.81-13.28 9.09-9 18.06-18.06 27.15-27 7.38-7.26 14.94-14.46 22.43-21.72L351 307.05c9.56-9.39 19.18-18.83 28.86-28.22a6.32 6.32 0 0 1 11.14 1.25 43.17 43.17 0 0 1 7.55 24.4 44.26 44.26 0 0 1-.23 4.46A40.72 40.72 0 0 1 388 332.55c-7.09 7.62-14.64 14.82-22 22.14-5.25 5.19-10.62 10.27-15.88 15.52-6.79 6.73-13.46 13.58-20.25 20.31-1 1.12-1.94 2.3-3 3.36l-6.67 6.91c-5 5-10.09 9.86-15 14.87s-10.55 10.87-15.8 16.34c-.47.53-1 .88-1.47 1.35-5.91 5.49-11.34 11-16.95 16.53-2.65 2.6-5.19 5.25-7.79 7.85-4.48 4.55-9.09 9-13.4 13.64-2.65 2.77-2.65 4.48.48 6.67a112.39 112.39 0 0 0 16.35 10.44 82.41 82.41 0 0 0 45.62 6.49 74.59 74.59 0 0 0 41.33-18.83c8.73-7.67 16.53-16.29 24.67-24.55 5.9-5.91 11.81-12.22 18.12-18.3l17.06-17.18c5.2-5.25 10.33-10.51 15.59-15.7s11.8-11.39 17.7-17.24 11.81-11.8 17.71-18.06a136.64 136.64 0 0 0 13-15.35 83.71 83.71 0 0 0 13.41-37.12 82.31 82.31 0 0 0 0-19.84 82.94 82.94 0 0 0-12.46-32.88 95.35 95.35 0 0 0-16.52-19c-16.35-16.23-32.65-32.58-48.64-49.17a37.19 37.19 0 0 0-27.65-12.34h-.22l-1.77.24z" style="fill:#fff;fill-rule:evenodd"/></g></g></g></svg>
  </div>
</body>
</html>

這個情境單純想實驗:若我們將這個空的 svg 本身或其父元素加上 display: none,是否能正常顯示?
結果跟情境 2 一樣,是不行的。

如果拿掉 svg 的父元素樣式(display: none)呢?可以正常顯示了!即使我們用 display: none 隱藏了第一個 icon 也依然正常。

喔對了,實際使用上有個要注意的小地方,由於這個空的 svg 仍會佔去畫面上一些位置,無法用 display: none 的情況下,可以將其寬高(width & height)皆設為 0,但必須加上 display: block 或是 position: absolute,否則 widthheight 是無法套用到 inline 元素上的。


小結

上述情境,其實不光是 linearGradient 會這樣,其他在 defs 標籤中的 maskclipPath 等元素也有可能發生這樣的情況。

先不論情境 2 跟 3 中,display: none 的情況是否為瀏覽器的實作與規範不同,情境 1 跟情境 2 都可以透過修改 id 為唯一值來解決。事實上,在 SVG 1.1 的 規範 中明確指出了 id 必須是唯一值,HTML 規範 中亦是如此。也就是說,相同 id 的用法並不合法。

不過實際應用上滿容易不小心就踩到這個雷的,以自身經驗來說,採用 React 進行開發時,經常把 svg 圖片以 React component (inline SVG) 的方式加入到 component 中,例如:

import MyIcon from './assets/myIcon.svg';

<MyIcon />

註:當然也可以以 <img src={svg} /> 的方式插入,但使用 inline SVG 確實有些方便之處,可參考 此處 的討論。不過這不在本文討論範圍,故不多做贅述。

其中若帶有 defs 的定義,而這些 id 值又沒有特別處理過的話,很容易就踩到 id 重複的問題。

或是用情境 3 的作法,將這些 defs 內容抽到一個空白的 svg 中單純作為定義使用,其他的 svg 再來使用它。不過以 import svg as react component 的情境來說,在實際應用上,這個解法可能並不是那麼方便。

那麼,也許可以選擇個別手動處理(例如說在那些帶有 id 的 svg 中使用 uuid 這類 package 產生 unique id),或更懶一些,可能可透過 babel plugin 自動處理 import 的 inline svg,這邊有一些討論與解法。


參考資料

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *