嵌入矩阵:谁能被 CSS 管到
同一颗心,用五种方式放进页面,再看哪些跟随外部 CSS 与宿主文字色变化、哪些不受影响——这就是图标系统为什么偏爱 inline 与 <use> 的根本原因。
| 把同一段 SVG 这样放进页面 | 外部 CSS 能改它内部? | JS / :hover? | currentColor 继承宿主? |
|---|---|---|---|
inline <svg> |
✅ 完全 | ✅ | ✅ |
<use href="#id">(同文档) |
✅ 可穿透 | ✅ | ✅ |
<img src=".svg"> |
❌ 隔离 | ❌ | ❌ |
background-image: url() |
❌ | ❌ | ❌ |
<object> / <iframe> |
❌ 跨文档 | ⚠️ 独立文档 | ❌ |
那几个隔离格,param() 提案想给它们开一扇传参口。
1 · 五种写法
只有 inline 和同文档 <use> 把图形真正接入了当前文档的 DOM 树,所以外部 CSS 选择器能选中、currentColor 能继承宿主的 color、:hover 也能命中。<img> 与 background-image 把 SVG 当作一张沙箱位图,内部 DOM 对外不可见;<object>
与 <iframe> 是另一个独立文档,外部 CSS 同样无法进入,但它内部的 <style> 有效。
2 · 复用三件套
上面那个能被 CSS 改色的 <use>,正是图标 sprite 系统的地基:把图形定义一次放进 <defs> 或 <symbol>(不渲染、待引用),页面各处用 <use href="#id"> 克隆。<symbol> 比 <g> 多一个自带的
viewBox,所以每次 <use> 都能缩放贴合。
注 · <use> 克隆出的内容在一棵 shadow tree 里,外部 CSS 选不中它的内部元素,写 use circle {…} 没用。但继承类属性(fill、color、自定义属性)能从 <use> 元素本身穿透下去——所以改色靠的是「在 use 上设
fill,让内部继承」,而不是直接选中内部。主题化图标的细节见 presentation attribute 一页。
3 · 两个反直觉特性
警示 · SVG 没有 z-index。元素的层叠顺序完全等于文档顺序,写在后面的覆盖前面的;要调整层级只能改变 DOM 位置,或用 <use> 重新引用。给 SVG 子元素写 z-index 无效。
警示 · pointer-events 在 SVG 里取值更多。除了 auto 与 none,还有
visiblePainted(默认,只有被填充或描边的可见部分响应点击)、fill(透明填充区也响应)、stroke、all。因此一个只描边的圆环,默认点击中间空心处不会触发,除非设 pointer-events: fill。