🔷 SVG × CSS:一块能被 CSS 管的画布
<canvas> 绘制后只剩像素;SVG 不同——每个图形都是 DOM 节点,能被 CSS 选中、被 :hover 命中、被 currentColor 染色,且缩放后不失真。这一特性 (retained-mode + 声明式) 决定了「CSS 能否、以及如何作用到 SVG 内部」。本系列不涉及 path 命令 (那是 css-paths 的主题),只讲 SVG 作为一种图形介质的运行机制:它如何进入页面、坐标系如何搭建、CSS 如何逐层驱动它的上色与描边、渐变为何能随形状缩放。
九页分三组。已落地的机制讲 SVG 能被 CSS 驱动的全部要件:嵌入矩阵、viewBox 坐标系、presentation attribute 优先级、transform 枢轴、fill / stroke 画笔、渐变与 *Units。综合应用把这些机制组合成一个真实场景:用 getBoundingClientRect 量出 DOM 坐标、实时生成连线 path,再以 scroll 位置驱动 clip-path 做进度高亮——文档目录连线的做法。边界与未来收两页:param() 提案想给隔离的外部 SVG 开一扇传参口,以及一份「SVG 还缺什么」的开发者反馈清单。本系列大量涉及 CSS cascade 与优先级,若需复习可参考 how-css-works。
已落地的 CSS × SVG 机制
SVG 能被 CSS 驱动,是因为它的图形是真实 DOM、上色 / 描边属性几乎都同时是 XML 属性和 CSS 属性。这六页用同一套模型逐层拆解。
嵌入矩阵:谁能被 CSS 管到
同一颗心,用 inline / <use> / <img> / background-image / <object> 五种方式放进页面,实测哪些能被外部 CSS 改色、被 currentColor 染、被 :hover 命中。复用三件套 <defs> / <use> / <symbol>,以及 SVG 没有 z-index、pointer-events 取值更多两条反直觉特性。
viewBox:SVG 自带的相机
width/height 是页面上的 viewport,viewBox 是架在其中的一台相机:改 w/h 推拉缩放、改 min-x/min-y 平移取景。拖四个值看绘图坐标与显示像素如何解耦;preserveAspectRatio 的 align × meet/slice 决定宽高比不符时怎么塞。
presentation attribute 优先级
fill="red" 其实是特指度为 0 的 presentation attribute,位于优先级链最底层,任何 CSS 规则都能覆盖。四层阶梯实测 cascade 胜出者;cx / r / d 升级为 CSS 几何属性可 transition;currentColor 与 var() 穿透 <use> 做主题化图标。
transform-origin:旋转枢轴在哪
SVG 内部图形元素的 transform-origin 默认 0 0、transform-box 默认 view-box,于是 rotate() 绕画布原点「公转」而非原地自转。拖角度看枢轴位置,transform-box: fill-box 才把枢轴钉回图形自己身上。
fill & stroke:描边与自绘
stroke-dasharray = 路径全长 + 滑动 dashoffset 实现「线条自我绘制」;linecap / linejoin 的端点与拐角;paint-order 切换填充与描边的先后;fill-rule 的 nonzero / evenodd 决定自交图形哪里算「里面」。
渐变与图案:画笔工厂
渐变和 <pattern> 是定义在 <defs> 里、被 url(#id) 引用的 paint server。调一支渐变笔看 spreadMethod;gradientUnits 的 objectBoundingBox vs userSpaceOnUse 是理解 SVG 所有 *Units 行为的钥匙。
综合应用
把上面的机制组合进一个真实场景:SVG 的图形是坐标驱动的,坐标可以来自 getBoundingClientRect 量出的真实 DOM 布局——于是「连接任意两个 DOM 节点」这件 HTML / CSS 做不到的事,交给一段实时生成、再被 scroll 驱动的 SVG。
边界与未来
已落地机制之外:隔离边界未来可能的破口,以及开发者眼中 SVG 仍缺失的能力。
param():给隔离 SVG 传参
<img> / background-image 引入的 SVG 是隔离沙箱,外层变量进不去。CSS Linked Parameters 草案的 param() 想在引用处把具名参数单向递进资源、内部用 env() 接住,一份文件随调用方染色。提案尚未落地,本页右图为模拟。
SVG 还缺什么
换个视角:开发者眼中 SVG 仍缺失的能力。文本不会自动换行(对照 <foreignObject>)、stroke 只有 center 无 inside / outside(clip / mask 模拟),以及性能、morphing、geometry API、无障碍、interop 等偏机制层面的缺口清单。
一条主线
viewBox 一改就缩放、为什么一条 CSS 规则能覆盖直接写在标签上的颜色、为什么渐变有时随形状缩放有时不随。相关链接
- Scalable Vector Graphics (SVG) 2 w3.org 规范本体:rendering、styling、几何属性、paint server 与 *Units 的权威定义,SVG 1.1 之上的修订版。
- SVG art II — fuma-nama fuma-nama.dev scroll-toc 页的来源:文档目录用 cubic Bézier 连接嵌套标题,再用 clip-path (而非 mask-image) 跟随 scroll 做高亮的实现思路。
- MDN · Element.getBoundingClientRect() developer.mozilla.org scroll-toc 页量 DOM 坐标的 API:返回元素相对 viewport 的 rect,减去 SVG 容器 rect 即得 path 坐标。
- MDN · clip-path developer.mozilla.org scroll-toc 页进度高亮的机制:inset() 矩形裁剪只在 compositor 阶段变化,不触发 layout / paint。
- MDN · SVG element reference developer.mozilla.org 全部 SVG 元素索引:defs / use / symbol / linearGradient / pattern 等逐个有专页与属性表。
- What's missing from SVG — Patrick Brosset patrickbrosset.com gaps 页的来源:综合 Chromium bug tracker、Interop 提案、State of CSS 2025 与社媒反馈,梳理开发者眼中 SVG 仍缺失的十余项能力。
- Can I use · SVG (basic support) caniuse.com embed / object 方式显示 SVG 的实时浏览器支持矩阵 (覆盖 SVG 1.1 基础特性)。
- CSS Linked Parameters Module Level 1 drafts.csswg.org link-params 页 param() 的来源:三处用法、资源内 env() 接收与 fallback 语义。早期草案,尚无浏览器实现。
- MDN · SVG from scratch (教程) developer.mozilla.org 官方系统教程:从基本形状、坐标系到 fill/stroke、渐变、文本,本系列的底料。
- MDN · SVG and CSS developer.mozilla.org presentation attribute 与 CSS property 的关系、优先级、哪些属性能用 CSS 控制。
- MDN · preserveAspectRatio developer.mozilla.org align (9 种) × meetOrSlice 的完整取值与图示,viewBox 一页的参考。
- Understanding SVG Coordinate Systems — Sara Soueidan sarasoueidan.com viewport / viewBox / preserveAspectRatio 三件套讲得最透的一篇长文。
-
MDN · gradientUnits
developer.mozilla.org
objectBoundingBox vs userSpaceOnUse —— 理解所有
*Units的钥匙。 - MDN · transform-box developer.mozilla.org view-box / fill-box / stroke-box —— 决定 transform 与 transform-origin 相对哪个盒子,SVG 旋转枢轴默认落在画布原点的根因。
- SVG Properties and CSS css-tricks.com 哪些 SVG presentation attribute 能改用 CSS 写、geometry property 升级清单。