基线从哪一行来:baseline-source 与 SVG 基线属性
02 · baseline 与 vertical-align 留了一个未展开的问题:inline-block 的 baseline 取最后一行,可同样装着多行内容的 inline-flex 拿的却是第一行。「从哪一行取 baseline」过去是各布局模型固定的默认值,CSS Inline Layout
L3 把它变成了一个可调的开关——baseline-source: auto | first | last。本页先实测这个开关;再补上「根本没有行可取」时的 fallback 规则(空盒子 /
→ margin 底边缘,本页把 margin 边参与对齐的过程直接演示出来);最后去 SVG 看同一个问题的另一套答案:dominant-baseline 与 alignment-baseline。
02 页「延伸:规范为什么这样定」小节提过的早期草案属性 inline-box-align(贺师俊答案里的名字),在 CSS Inline Layout L3 里落地成了 baseline-source。同一份规范还把 vertical-align 重定义为 baseline-source / alignment-baseline / baseline-shift 三个
longhand 的 shorthand——加上 02 页讲的 vertical-align 本身,本页正好把这只 shorthand 拆完。
1 · baseline-source:inline-block 默认 last,inline-flex 默认 first
一行里:外部文本 test + 两个都装着 line1 / line2 两行内容的盒子,左边 inline-block、右边 inline-flex(列方向)。绿色虚线是外部文本的 baseline,玫红短线是每个盒子内部 L1 / L2 两行各自的
baseline(实测画出)。默认(auto)下两盒一个沉一个浮——切 baseline-source 看它们「换一行坐线」:
auto 到底等于什么?规范规定 auto 对 inline-block 表现为 last,对其余 inline-level 盒(inline-flex / inline-grid)表现为 first——这正是「同样两行内容,换个 display 就错开一行」的根源。baseline-source 只是把这个写死的默认暴露成属性:聊天气泡里「昵称 + 正文」想按昵称行对齐头像、多行 tag 想按首行对齐相邻文本,以前要靠包一层 hack,现在一行声明。
2 · fallback 规则:没有行可取时,baseline = margin 底边缘
first / last 都有个前提:盒子里得有 in-flow 的行。CSS 2.1 §10.8.1 规定,inline-block 只要「没有 in-flow 行内内容」或 overflow 不是 visible,baseline 就是它的 margin 底边缘(bottom margin edge)——这条 fallback
规则优先级最高,baseline-source 无法改变它。02 页用它解释负 margin 谜题,这里直接演示「margin 边」的参与:拖 margin-bottom,看对齐线跟着 margin 边移动、盒子被整体抬高。
对照:fallback 生效时(空盒 / overflow:hidden),橙色 margin 边始终压在绿线上,margin-bottom 越大盒子被抬得越高——「坐在线上的是 margin 边,不是 border 边」。切回「有文字 + visible」,对齐改用玫红的文字 baseline,margin-bottom 立刻退场(只影响后续布局,不再参与对齐)。
3 · SVG:dominant-baseline——「主基线」选哪条线
HTML 文本只直接暴露一条 alphabetic baseline,但字体里其实藏着一组基线(alphabetic / central / hanging / ideographic …)。SVG 的 <text> 用 dominant-baseline 选「哪条线当主基线」——即 y 坐标钉住的是哪条线。下面一条绿色参考线(y
相同),每个词用自己名字对应的值对齐,点按钮高亮逐个看:
4 · SVG:alignment-baseline——自己拿哪条线去挂父级
dominant-baseline 是站在父级 / 基准一侧:定出「主基线在哪」。alignment-baseline 则站在内容一侧:一个 <tspan> / <textPath> 拿自己的哪条基线去对父级的对应基线。下面外层 24px 文本里嵌一个 13px 的
tspan,切它的 alignment-baseline 看小字相对大字怎么「挂」:
5 · 总结
三个 longhand 的分工(CSS Inline L3 口径):vertical-align 其实是个 shorthand,展开为 baseline-source(多行盒拿自己哪一行的 baseline 对外)+ alignment-baseline(拿自己的哪条基线去挂父级)+
baseline-shift(挂好之后再位移多少)。HTML 里写 vertical-align: middle,本质就是设 alignment-baseline;SVG 文本没有 vertical-align,这两个 longhand 便直接可用,再配上父级一侧的 dominant-baseline 选主基线。而当盒子里根本没有行(空盒 /
),一切让位给 CSS 2.1 的 fallback 规则:baseline = margin 底边缘。