iT邦幫忙

2026 iThome 鐵人賽

DAY 7
0
Modern Web

從實務需求出發:前端視覺與 UI 互動開發實踐系列 第 7 篇

【Day 07】SVG 實作:用 fill / stroke 告別海量 icon 靜態圖檔

  • 分享至 

  • xImage
  •  

SVG 最常應用在 icon 上,不只因為它是向量圖,icon 也很常出現在按鈕等互動元素中,會隨著狀態改變樣式。試想一下,如果每一種狀態的 icon 都要從設計稿匯出一個圖檔,靜態檔案的數量膨脹好幾倍。光想像就讓人瑟瑟發抖。

今天會以 button 中的 icon 為例,講解如何用 fill 與 stroke 修改 inline SVG 的顏色。來更優雅地處理 icon 吧!

⚠️這些技巧只適用於直接寫在 HTML 裡的 inline SVG。如果用 <img src="star.svg"> 或 CSS 的 background-image 載入,SVG 會被當成獨立的圖片,外層的 CSS 與 currentColor 都無法影響它。


小試身手

昨天的 SVG 介紹中,我們知道能用 fill 與 stroke 來設定圖形的顏色。除了直接修改 <svg> 的屬性外,還有更多應用場景。先來看看該如何讓按鈕中 SVG icon 的顏色與尺寸,跟著按鈕的文字顏色與字體大小同步。

先介紹今天的助教——星星。參考註解,可以清楚知道 <svg> 內的四個標籤分別繪製了哪部分。現在的星星是一個固定 200px × 200px 的黑框星星。

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200">
	<!-- 星星:每個角都用 Q 曲線切成圓角 -->
	<path
		d="M96.01 23.07 ... Z"
		fill="none"
		stroke="#000"
		stroke-width="4"
		stroke-linejoin="round"
	/>

	<!-- 眼睛 -->
	<circle cx="84" cy="96" r="6" fill="#000" />
	<circle cx="116" cy="96" r="6" fill="#000" />

	<!-- 嘴巴 -->
	<path d="M80 113 Q100 136 120 113" fill="none" stroke="#000" stroke-width="4" stroke-linecap="round" />
</svg>

https://ithelp.ithome.com.tw/upload/images/20260922/20184345uSr7Gppd3H.png

現在,要讓圖形的顏色能套用外層 <button> 的設定。只要把圖形的 fill / stroke 改成 currentColor,SVG 圖形就會吃到外層的文字顏色。

接著,順便讓圖形尺寸套用按鈕的文字設定,把 <svg> 上面指定 width 與 height 拿掉,改在 CSS 將寬高設為 1em。

<button type="button" class="star-btn">
	<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
		<path
			d="M96.01 23.07 ... Z"
			fill="none"
			stroke="currentColor"
			stroke-width="4"
			stroke-linejoin="round"
            aria-hidden="true"
		/>

		<!-- 眼睛 -->
		<circle cx="84" cy="96" r="6" fill="currentColor" />
		<circle cx="116" cy="96" r="6" fill="currentColor" />

		<!-- 嘴巴 -->
		<path d="M80 113 Q100 136 120 113" fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round" />
	</svg>
	<span>star</span>
</button>
.star-btn {
	color: #000;
	font-size: 40px;

	svg {
		width: 1em;
		height: 1em;
	}
}

.star-btn:hover {
	color: orange;
	background: yellow;
	border-color: orange;
	font-size: 48px;
}

這樣一個附 icon 的按鈕就完成了。顏色與尺寸只需要設定在 <button> 這一層,icon 就會跟著按鈕文字一起變化,維護起來簡單不少。

多種色彩

如果顏色變化不只一種,可以用 CSS 分別設定不同標籤的 fill / stroke。先把剛剛寫死在 HTML 標籤上的屬性移除,改用 class 選取器來設定。例如,我想要分開設定星星的填色跟嘴巴顏色,就能在對應的 class 設定 fill 與 stroke。

原本嘴巴是一條線,不是封閉圖形,所以要寫 fill: none。若把 HTML 上的 fill="none" 移除後,圖形會回到預設的黑色填充。

<button type="button" class="star-btn">
	<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200">
		<path class="star-shape" d="M96.01 23.07 ... Z" stroke-width="4" stroke-linejoin="round" aria-hidden="true" />

		<!-- 眼睛 -->
		<circle cx="84" cy="96" r="6" fill="currentColor" />
		<circle cx="116" cy="96" r="6" fill="currentColor" />

		<!-- 嘴巴 -->
		<path class="star-mouth" d="M80 113 Q100 136 120 113" stroke-width="4" stroke-linecap="round" />
	</svg>
	<span>star</span>
</button>
.star-btn {
	.star-shape {
		fill: #808080;
		stroke: currentColor;
	}
	.star-mouth {
		fill: pink;
		stroke: pink;
	}
}

.star-btn:hover {
	color: orange;

	.star-shape {
		fill: yellow;
	}
}

外框跟隨文字顏色(currentColor),星星填色與嘴巴顏色則各自獨立,互不影響。另外,CSS 的優先權高於標籤上的屬性,所以即使 HTML 上還留著 fill,CSS 也能直接覆蓋它。

同理,stroke-width、stroke-linecap 等外觀相關的屬性,也都可以改用 CSS 來寫。


完整範例

Codepen 連結

回到一開始的問題:以前 default、hover、disabled 每種狀態與顏色,都要一個圖檔;現在只要一份 SVG,狀態與顏色都交給 CSS 決定。蒸蚌!!

.
.
.
透過相對直觀的 fill / stroke,我們知道可以直接在 SVG 標籤上設定屬性,也能利用 CSS 與選擇器做更細緻的樣式控制。

明天,我想來一點漸層。漸層不能直接寫在 fill 裡,需要先用 <defs> 定義,再透過 url(#id) 引用。看看曾經讓我傷透腦筋的漸層按鈕吧!


上一篇
【Day 06】SVG 基礎:我把圖片內嵌在 HTML 了!
下一篇
【Day 08】 SVG 實作:是漸層,我加了漸層
系列文
從實務需求出發:前端視覺與 UI 互動開發實踐 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言