@supports 里的三条声明
配方的后半段是一个条件块:
@supports (field-sizing: content) {
max-block-size: var(--_max-rows);
resize: unset;
field-sizing: content;
}
field-sizing: content 出现在自己的探测块里是自然的。另外两条为何要陪着它进来,需要分别说明。field-sizing 本身的取值语义与它在 <input> / <select> 上的效果见
field-sizing: content:textarea 一行 CSS 自动长高,本页只谈它与配方其余声明的相互作用。
1 · 它改写的是两个方向的固有尺寸
field-sizing: content 把控件的固有尺寸从「属性给定的行列数」换成「内容实际占多大」。这句话里的尺寸是双向的:高度跟随内容行数,宽度也跟随内容长度。
后半句是一个容易踩空的地方。一个 16px monospace、padding: 1em、内容只有一个字符 a 的控件,加上 field-sizing: content 后实测宽度只有 43.64px——一个字符加 padding 的宽度。在 420px 的容器里它缩成一个小方块。
配方没有踩到这个坑,因为第二条声明 inline-size: stretch 已经把 inline 方向钉死了:显式的 inline-size 压过固有尺寸,控件宽度回到容器的 420px,只有 block 方向留给内容驱动。这是配方内部一条不显眼的依赖——删掉 inline-size 那两行,垮掉的不是宽度铺满,是控件形状。
inline-size 观察宽度塌缩,加长内容观察高度增长与封顶后转内部滚动。2 · rows 属性到此才真正失效
行数尺寸与 lh 单位 §2 量到 rows 与 min-block-size 是取较大者,rows="10" 的控件仍有十行高。加上 field-sizing: content 后这条路断了:固有高度不再由 rows 计算,而是由内容行数计算。rows="10"
配一行内容、且不设下限时,实测边框盒高 58px——一行 24px 加 padding 与 border 的 34px,rows 的十行不留痕迹。
配方原注释把这个效果记在了 min-block-size 那一条上,位置差了四行。
3 · max-block-size 为何不能独立存在
max-block-size: calc(20 * 1lh) 的意图是「最多长到二十行」。这个意图只在高度会自己增长时才成立。
没有 field-sizing: content 的浏览器里,控件高度由 rows 与 min-block-size 共同决定,是一个静态值,封顶只可能起反作用——rows="30" 的控件会被砍到二十行,而这个砍法既不是作者的本意,也无从察觉。把它关进
@supports 之后,不支持的浏览器完整保留 rows 给出的高度。
支持的浏览器里它才开始工作:内容超过上限后高度停住,溢出部分转为内部滚动。实测十二行内容配 max-block-size: calc(8 * 1lh),边框盒高 226px(八行 192px 加 34px),scrollHeight 320px 大于 clientHeight 224px,滚动条出现。
4 · resize: unset 是一条可访问性开关
resize 的 initial value 是 none,<textarea> 的 both 来自 UA stylesheet。resize: unset 取 initial value,于是把用户拖动右下角改变尺寸的能力收走了,实测计算值从 both 变成 none。
收走它的前提是控件已经不需要手动调整——高度自己跟着内容走。在不支持 field-sizing 的浏览器里这个前提不成立:高度是死的,内容一多就只能在小窗口里滚动,而拖动把手是用户唯一的补救手段。配方把
resize: unset 放进条件块,等于写下一句「只有当浏览器能替用户长高时,才收走用户自己动手的权利」。
这是整份配方里唯一一条与能力探测绑定的交互决策,其余六条都只关乎排版。
注 · 三家浏览器均已支持 field-sizing:Chromium 123(2024-03)、Safari 26.2(2025-12)、Firefox 152(2026-06)(兼容性据 MDN BCD,核对于 2026-09)。@supports 守的因此不再是「某个引擎没做」,而是尚未升级的旧版本——Safari 与 Firefox
的落地都在近一年内,这道门还不到可以拆的时候。