圖片、背景與 CSS 造型
圖片格式與尺寸怎麼選、背景圖上的文字怎麼保證看得見、不用圖片就能做出來的十種背景,以及紋理與遮罩。
1. 圖片的四件必做
一、一定要有尺寸
<img src="hero.avif" width="1600" height="900" alt="…" />
有了寬高,瀏覽器在圖片載入前就能保留空間。沒有的話,圖片一到位就把下面的內容往下推(CLS)。
不知道原始尺寸時用 aspect-ratio:
.thumb { aspect-ratio: 16 / 9; object-fit: cover; }
二、格式順序
<picture>
<source srcset="hero.avif" type="image/avif" />
<source srcset="hero.webp" type="image/webp" />
<img src="hero.jpg" width="1600" height="900" alt="…" />
</picture>
AVIF 通常比 JPEG 小 50%,WebP 小 30%。照片用 AVIF/WebP,圖示與 logo 用 SVG(無限清晰、可以吃 CSS 變數換色)。
三、responsive srcset
<img
src="hero-800.avif"
srcset="hero-400.avif 400w, hero-800.avif 800w, hero-1600.avif 1600w"
sizes="(max-width: 700px) 100vw, 50vw"
width="1600" height="900" alt="…" />
沒有 sizes 的話瀏覽器會假設圖片滿版,於是手機也下載大圖。
四、載入優先序
- 首屏主視覺:
fetchpriority="high",不要loading="lazy" - 其他全部:
loading="lazy"decoding="async"
對首屏圖片加 lazy 是常見的反效果 —— 它會讓 LCP 變慢。
2. alt 怎麼寫
| 圖片類型 | alt |
|---|---|
| 純裝飾 | alt=""(空字串,不是省略) |
| 有資訊 | 描述資訊,不是描述畫面 |
| 圖片就是連結 | 描述連結會去哪裡 |
| 圖表 | 講結論:「營收從 1 月的 120 萬成長到 6 月的 310 萬」 |
alt="" 和沒有 alt 不一樣:前者是「這張圖可以跳過」,後者會讓螢幕閱讀器唸出檔名。
3. 背景圖上的文字
永遠不要直接把文字放在照片上。 照片的亮度會變,文字一定會在某個裝置上讀不到。
三種處理,依強度排序:
一、漸層 scrim(最常用)
.hero::before {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(
190deg,
color-mix(in srgb, var(--ds-canvas) 72%, transparent) 0%,
color-mix(in srgb, var(--ds-canvas) 22%, transparent) 46%,
transparent 70%
);
}
color-mix() 讓 scrim 跟著主題色走,換深色主題時不需要另外寫一套。
二、文字自帶底:黑色圓角長條加白字。清楚、可預測,也是 Neon Ink 用的手法。
三、模糊局部:backdrop-filter: blur(8px) 加半透明底。漂亮但耗效能,只用在小面積。
不要用 text-shadow 當唯一手段 —— 在複雜背景上仍然讀不清,而且會讓文字看起來髒。
4. 不用圖片的背景
網點(半調)
background-image: radial-gradient(currentColor 1px, transparent 1.2px);
background-size: 14px 14px;
opacity: 0.06;
方格紙
background-image:
linear-gradient(var(--ds-line) 1px, transparent 1px),
linear-gradient(90deg, var(--ds-line) 1px, transparent 1px);
background-size: 32px 32px;
斜線
background: repeating-linear-gradient(
45deg,
var(--ds-line) 0 1px,
transparent 1px 10px
);
光暈
background:
radial-gradient(900px 500px at 12% -8%, rgb(124 92 255 / 0.2), transparent 62%),
radial-gradient(700px 420px at 92% 8%, rgb(34 211 238 / 0.12), transparent 60%);
一個光源比三個好。 多個光源會讓畫面沒有方向感。
紙紋(SVG 雜訊,零請求)
--ds-texture: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='160' height='160' filter='url(%23n)' opacity='0.05'/></svg>");
注意 #n 在 data URI 裡必須寫成 %23n,否則會被當成 fragment。
漸層邊框
.gradient-border {
border: 1px solid transparent;
background:
linear-gradient(var(--ds-surface), var(--ds-surface)) padding-box,
linear-gradient(135deg, var(--ds-accent), transparent) border-box;
}
遮罩淡出
.fade-bottom {
mask-image: linear-gradient(to bottom, #000 60%, transparent);
}
用在插畫出血、長清單的下緣、無限捲動的邊界。
5. SVG 插畫
SVG 的最大優勢是它會跟著主題換色:
.art .ink { fill: var(--ds-ink); }
.art .blast { fill: var(--ds-accent); }
一份插畫,六種風格都對,不需要六個匯出檔。
程序生成的圖形要確定性,不要用 Math.random() —— 伺服器和瀏覽器會產生不同結果,hydration 會警告,畫面也會跳。用固定的資料陣列。
6. 效能預算
| 項目 | 上限 |
|---|---|
| 首屏所有圖片 | 250KB |
| 單張主視覺 | 150KB |
| 圖示 | 一律 SVG inline 或 sprite |
| 字型檔 | 兩個家族,各 ≤ 2 個字重 |
檢查方式:DevTools → Network → 篩選 Img → 看 transferred 總量。
7. 檢查清單
- 每張圖都有
widthheight或aspect-ratio - 有 AVIF / WebP,JPEG 只當 fallback
- 有
srcset與sizes - 首屏圖
fetchpriority="high"且沒有 lazy - 其他圖
loading="lazy"decoding="async" - 裝飾圖
alt="",資訊圖有真正的描述 - 背景上的文字有 scrim 或自帶底
- 能用 CSS 做的紋理沒有用圖片
- 程序生成的圖形是確定性的