尺寸取值:width / height / min / max 的各种值
flex-basis 一页讲了 item 主轴尺寸如何确定、为何 flex-basis 覆盖 width。这页退一步,系统看 width / height / min-* / max-* 本身能接哪些取值:固定
<length>、相对 <percentage>、内容驱动的 min-content / max-content / fit-content()、以及较新的 stretch;再讲清百分比相对谁解析、min/max 如何夹取最终尺寸。示例在 flex
容器里跑(item 设 flex: none,其主轴尺寸即 width),但取值规则对普通块同样适用。
1 · width 取值之旅(实测)
容器定宽 360px,里面一个 flex: none 的 item,文字含一个长单词。切换 width 取值,再叠加 min-width / max-width 看夹取效果。item 宽度为真实 getBoundingClientRect 实测。
2 · 取值类型一览
| 取值 | 含义 | 备注 |
|---|---|---|
auto |
由布局算法决定(初始值) | 普通块的 width: auto 撑满可用宽;flex item 的主轴 auto 走 flex-basis 流程。 |
<length> |
固定长度,如 120px / 8rem |
受 box-sizing 影响(默认 content-box)。 |
<percentage> |
相对包含块对应维度 | width% ← 包含块宽;height% ← 包含块高(高度不确定时退化为 auto,见下)。 |
min-content |
内容能压到的最小尺寸 | 横向 ≈ 最长不可断单词的宽度。 |
max-content |
内容不换行时的理想尺寸 | 横向 ≈ 全部文字排一行的宽度。 |
fit-content |
在可用空间内自适应,但不超 max-content |
= min(max-content, max(min-content, stretch))。 |
fit-content(<LP>) |
用给定值替代「可用空间」做夹取 | = min(max-content, max(min-content, <LP>))。 |
stretch |
让 margin box 撑满包含块 | 较新关键字(旧前缀 -webkit-fill-available),支持有限,不支持时按 auto 表现。 |
百分比相对谁? width / min-width / max-width 的百分比相对包含块宽度;height 系列相对包含块高度。一个高频陷阱:margin / padding 的百分比无论横竖都相对包含块
inline 尺寸(通常是宽度)——所以 padding-top: 50% 是按宽度算的(常用于固定宽高比占位)。
3 · 百分比高度:为什么常常「不生效」
两个父盒都给子元素设 height: 50%。左父盒显式 height: 200px,右父盒高度 auto(由内容撑开)。子元素高度为实测值:左 = 父高一半,右 = 退化为 auto(按内容)。
规则: 当包含块的高度未显式确定(高度为 auto、取决于内容)时,子元素的百分比 height 计算为 auto——即不生效、回到按内容定高。宽度没有这个问题,因为块的宽度通常是确定的。绝对定位元素与 flex/grid
在部分情形下有各自的确定尺寸规则,不在此列。
4 · min / max 如何夹取
| 属性 | 默认值 | 作用 |
|---|---|---|
min-width / min-height |
auto |
下界。普通块里 auto ≈ 0;flex item 的 min-width: auto 是「自动最小尺寸」≈ min-content——这正是 flex item 默认不会缩到内容以下的原因。
|
max-width / max-height |
none |
上界(none = 不限)。 |
夹取顺序: 先取 width(或布局算出的尺寸),用 max 压上界、再用 min 顶下界——所以 min 的优先级高于 max:当 min-width > max-width 时,最终用 min-width。在 flex 里想让 item 真正缩到内容以下,需显式 min-width: 0(列向 min-height: 0),见 flex-basis 页。
5 · 物理尺寸 vs 逻辑尺寸:inline-size / block-size
上面的 width / height / min-* / max-* 都是物理属性(绑定屏幕的横、竖)。CSS Logical Properties 另给一组逻辑等价物,跟随 writing-mode / direction 翻转:inline-size
沿文字流方向、block-size 沿块堆叠方向。取值空间与 width / height 完全一致。
下面的盒子固定 inline-size: 160px / block-size: 80px。切 writing-mode 看它如何在横排=宽、竖排=高之间翻转(实测 width / height)。
| 逻辑属性 | 横排 horizontal-tb |
竖排 vertical-rl / lr |
|---|---|---|
inline-size |
width |
height |
block-size |
height |
width |
min-inline-size / max-inline-size |
min-width / max-width |
min-height / max-height |
min-block-size / max-block-size |
min-height / max-height |
min-width / max-width |
与 flex 的关系: flex 的主轴 / 交叉轴本就是逻辑概念——flex-direction: row 的主轴即 inline 轴(随 writing-mode / direction 改向)、column 的主轴即 block 轴。因此
flex-basis 度量的正是主轴方向的 inline-size 或 block-size。用逻辑属性写 flex item 的尺寸,可天然跟随书写方向而无需改属性名,这也是 flex 布局对国际化(RTL / 竖排)友好的原因之一。
6 · 长度单位:与 layout 相关的几类
上面的 <length> 不止 px。布局里真正常用、且各有「相对谁」的单位分四类:字体相对、视口相对、容器相对,以及把它们组合起来的数学函数。选错参照系是响应式布局最常见的错误(例如该跟容器走却写了 vw)。
| 类别 | 单位 | 相对谁 | layout 用途 / 备注 |
|---|---|---|---|
| 绝对 | px |
CSS 像素 | 固定尺寸基线;不随字号 / 视口缩放。 |
| 字体相对 | rem |
根元素 font-size |
全局可缩放的间距 / 尺寸基准,不受局部字号影响。 |
| 字体相对 | em |
本元素 font-size(用在 font-size 上则取父级) |
随字号缩放;嵌套时会复合放大(见下)。 |
| 字体相对 | ch |
字形「0」的 advance 宽 | 近似字符宽,做可读行宽 max-width: 60ch。 |
| 字体相对 | lh |
本元素 line-height |
按行高对齐的间距(rlh = 根行高)。 |
| 视口相对 | vw / vh |
视口宽 / 高(vh = 大视口 lvh) |
全屏区块。vh 在手机上偏大,见下。 |
| 视口相对 | vmin / vmax |
vw、vh 的小 / 大者 |
随视口的方形元素 / 自适应留白。 |
| 视口相对 | vi / vb |
视口 inline / block 向 | 逻辑版视口单位,随 writing-mode。 |
| 视口相对 | svh / lvh / dvh |
小 / 大 / 动态视口高 | 手机地址栏问题的解药(见下)。 |
| 容器相对 | cqw / cqh |
查询容器 宽 / 高的 1% | 组件相对尺寸;需祖先设 container-type。 |
| 容器相对 | cqi / cqb |
查询容器 inline / block 的 1% | 逻辑版容器单位(常用 cqi)。 |
| 容器相对 | cqmin / cqmax |
容器 inline、block 的小 / 大者 | 无合格容器时回退到 small viewport(sv*)。 |
| 函数组合 | clamp() / min() / max() |
组合上述单位 | 流式尺寸:clamp(1rem, 2vw + 1rem, 3rem) 在上下界间随视口平滑变化。 |
| (grid) | fr |
grid 轨道剩余空间的份额 | 只能用于 grid-template-*,不能用于 width / flex-basis。 |
7 · 容器单位 cqw:跟随容器,而非视口
外层设 container-type: inline-size 成为查询容器,内部 child 用 width: 50cqw / font-size: 7cqw。拖动改外层宽度——child 尺寸跟着这个容器缩放(实测约为容器 inline
尺寸的一半),与视口无关。这正是组件级响应式的基础:同一个组件放进窄侧栏或宽主区,靠 cqw / cqi 自适应,而不必依赖 vw 或断点。
手机上的 100vh 问题。 vh 等于大视口(lvh,地址栏收起时的高度),所以地址栏显示时
height: 100vh 会比可见区域更高、底部被切走。解药:svh(小视口,始终可见的最小高度)、dvh(动态,随地址栏伸缩实时变化)。全屏区块常用 min-height: 100svh 或 100dvh 替代 100vh(dvh
会在滚动时重算,注意性能)。
两个易错点。 其一,em 复合:父子都用 em 时逐层相乘——父 font-size: 1.5em、子再 1.5em,子的实际是祖父的 2.25 倍;要稳定基准用 rem。其二,fr 是 grid 轨道单位,不是 <length>,不能写进 width 或 flex-basis;flex 里「按比例分配」用 flex-grow(见 flex 简写)。