width: 50% 相对于包含块的宽度,通常是父元素内容区域宽度;height 百分比需父元素有显式高度才生效;padding/margin 百分比均以包含块宽度为基准;绝对定位元素参考最近定位祖先的 padding-box 或视口。

width: 50% 是相对于谁的宽度?
是相对于它的包含块(containing block)的宽度,绝大多数情况下就是父元素的内容区域宽度(content-box width)
注意:不是父元素整个盒子(含 padding/border/margin),也不是视口或祖先元素——除非你用了 position: absolute 或 fixed。
- 普通流中(
position: Static或relative):父元素的width值(不含 padding/border)就是参考值 - 父元素
width: auto且未设限制(如max-width)时,它可能由内容撑开 → 此时子元素的width: 50%会基于这个“撑开后的宽度”计算,容易意外变宽 - 父元素没设
width,又没其他约束(比如 flex 容器默认 stretch),那它的宽度可能是 0 或不可预测 → 子元素百分比宽度可能失效或为 0
为什么 height 百分比经常不生效?
因为 height: 50% 是相对于父元素的 高度,而父元素高度默认是 auto —— 这意味着它没有明确的“计算基准”,浏览器无法算出 50% 是多少。
- 父元素必须有显式高度(如
height: 300px、height: 100vh、或height: 100%且其父级也层层定义了高度) -
min-height或max-height不足以激活百分比高度 - Flex / Grid 容器中,子项的
height: 100%在某些场景下可生效,但本质仍是依赖容器自身已有高度
padding/margin 百分比为什么都按父元素宽度算?
css 规范强制规定:padding-top、padding-bottom、margin-top、margin-bottom 的百分比,全部以包含块的宽度为基准 —— 和方向无关。
立即学习“前端免费学习笔记(深入)”;
这看似反直觉,却是实现响应式比例布局的关键机制:
- 用
padding-top: 100%+height: 0+position: relative可创建正方形容器(宽高比 1:1) - 用
padding-bottom: 75%配合height: 0实现 4:3 宽高比(因为 3/4 = 0.75) - 如果误以为
padding-top: 10%是父元素高度的 10%,结果会远小于预期(尤其在窄屏高容器中)
绝对定位元素的百分比参考系变了
一旦子元素设了 position: absolute,它的包含块就不再是你直觉里的“父元素”,而是向上查找第一个 position 不为 static 的祖先(如 relative、absolute、fixed)—— 并且参考的是该祖先的 padding-box(内容区 + 内边距)。
- 没找到定位祖先?那就以视口(viewport)为参考,
left: 20%就是视口宽度的 20% - 父元素加了
padding: 20px,那么width: 100%的绝对定位子元素,实际宽度 = 祖先 padding-box 宽度 = 父内容宽 + 40px - 常见错误:忘了给定位父元素加
position: relative,导致子元素“飞出”预期位置
真正难的不是记住规则,而是每次写 % 时,下意识问一句:“这个百分比,此刻的参考系到底是谁?它的那个尺寸现在是多少?” —— 尤其当嵌套多层、混合定位和 flex 时,光靠经验很容易翻车。