CSS 与布局 / 🔷 SVG × CSS:一块能被 CSS 管的画布 / 嵌入矩阵:谁能被 CSS 管到 待审核 1 / 9
embed · 嵌入矩阵

嵌入矩阵:谁能被 CSS 管到

同一颗心,用五种方式放进页面,再看哪些跟随外部 CSS 与宿主文字色变化、哪些不受影响——这就是图标系统为什么偏爱 inline 与 <use> 的根本原因。

表 0-1 · 五种嵌入方式在三项能力上的对照。
把同一段 SVG 这样放进页面 外部 CSS 能改它内部? JS / :hover? currentColor 继承宿主?
inline <svg> ✅ 完全
<use href="#id">(同文档) ✅ 可穿透
<img src=".svg"> ❌ 隔离
background-image: url()
<object> / <iframe> ❌ 跨文档 ⚠️ 独立文档

那几个隔离格,param() 提案想给它们开一扇传参口。

图 0-1 · 逐格实测。一个开关让外部 CSS 把 fill 改为绿色,另一个改宿主文字色(currentColor 的来源)。

1 · 五种写法

只有 inline 和同文档 <use> 把图形真正接入了当前文档的 DOM 树,所以外部 CSS 选择器能选中、currentColor 能继承宿主的 color:hover 也能命中。<img>background-image 把 SVG 当作一张沙箱位图,内部 DOM 对外不可见;<object><iframe> 是另一个独立文档,外部 CSS 同样无法进入,但它内部的 <style> 有效。

图 1-1 · 五种写法的代码对照。

2 · 复用三件套

上面那个能被 CSS 改色的 <use>,正是图标 sprite 系统的地基:把图形定义一次放进 <defs><symbol>(不渲染、待引用),页面各处用 <use href="#id"> 克隆。<symbol><g> 多一个自带的 viewBox,所以每次 <use> 都能缩放贴合。

图 2-1 · defs、symbol、use 三件套的写法。

注 · <use> 克隆出的内容在一棵 shadow tree 里,外部 CSS 选不中它的内部元素,写 use circle {…} 没用。但继承类属性(fillcolor、自定义属性)能从 <use> 元素本身穿透下去——所以改色靠的是「在 use 上设 fill,让内部继承」,而不是直接选中内部。主题化图标的细节见 presentation attribute 一页。

3 · 两个反直觉特性

警示 · SVG 没有 z-index。元素的层叠顺序完全等于文档顺序,写在后面的覆盖前面的;要调整层级只能改变 DOM 位置,或用 <use> 重新引用。给 SVG 子元素写 z-index 无效。

警示 · pointer-events 在 SVG 里取值更多。除了 autonone,还有 visiblePainted(默认,只有被填充或描边的可见部分响应点击)、fill(透明填充区也响应)、strokeall。因此一个只描边的圆环,默认点击中间空心处不会触发,除非设 pointer-events: fill