CSS 中的百分比单位始终基于包含块(Containing Block)进行计算。包含块的定义取决于元素的定位属性:
position: static
或 relative
):包含块是最近的块级容器祖先的内容区域。position: absolute
:包含块是最近的 position
不为 static
的祖先元素的内容区域。若无此类祖先,则为 initial containing block
(通常是视口)。position: fixed
:包含块始终是视口。理解这一点对于准确预测百分比单位的行为至关重要。
width
、min-width
、max-width
- 相对于包含块的内容宽度计算。1.parent { width: 400px; }2.child { width: 50%; } /* 结果为200px */
height
、min-height
、max-height
- 相对于包含块的内容高度计算。1.parent { height: 300px; }2.child { height: 50%; } /* 结果为150px */
margin
和 padding
- 均相对于包含块的内容宽度计算。1.parent { width: 400px; height: 200px; }2.child {3padding-top: 10%; /* 结果为40px(基于宽度) */4margin-bottom: 5%; /* 结果为20px(基于宽度) */5}
注意:垂直方向的 margin
可能受外边距合并(margin collapsing)影响,需结合上下文理解。
top
、right
、bottom
、left
- 分别相对于包含块的高度或宽度。font-size
- 相对于父元素的计算字体大小。transform: translate()
- 相对于元素自身的尺寸。创建一个随屏幕变化的居中容器:
1.container {2width: 90%; /* 占屏幕宽度的90% */3max-width: 1200px; /* 限制最大宽度 */4margin: 0 auto; /* 水平居中 */5}
这种布局在手机上占据更多空间,在桌面端则不会过宽,提供更好的阅读体验。
确保图片永远不会溢出其容器:
10.image-container {20width: 100%;30overflow: hidden; /* 防止图片溢出 */40}5060img {70width: 100%; /* 图片宽度占满容器 */80height: auto; /* 保持宽高比 */90display: block; /* 消除底部间隙 */10}
传统方法(适用所有浏览器)
10.video-container {20position: relative;30width: 100%;40padding-bottom: 56.25%; /* 16:9 比例 = (9÷16)×100% */50background: #eee;60}7080.video-content {90position: absolute;10top: 0;11left: 0;12width: 100%;13height: 100%;14}
利用垂直 padding
相对于宽度计算的特性,形成固定宽高比的容器。
现代方法(需要现代浏览器支持)
1.modern-box {2width: 100%;3aspect-ratio: 16 / 9;4background: #eee;5}
aspect-ratio
属性使得这一技术更加直观和易用。
实现不论尺寸大小都能精确居中的元素:
10.parent {20position: relative;30height: 400px;40}5060.centered {70position: absolute;80top: 50%;90left: 50%;10transform: translate(-50%, -50%); /* 基于自身尺寸的 -50% */11/* 元素的中心点正好位于父元素中心 */12}
问题:当父元素高度为 auto
时,子元素的百分比高度被视为 auto
,而非基于父元素高度计算,导致“失效”。
1.parent {2/* 没有明确设置高度 */3}45.child {6height: 50%; /* 被视为 auto */7}
解决方案:
.parent { height: 500px; }
.child { height: 50vh; } /* 视口高度的50% */
1.parent {2display: flex;3height: 400px;4}5.child {6flex: 1; /* 自动占满可用空间 */7}
垂直方向的 padding
和 margin
百分比是基于包含块的宽度计算的:
1.box {2width: 400px;3height: 200px;4padding-top: 20%; /* 结果为80px(400px的20%) */5}
解决方案:
margin
和 padding
百分比均基于宽度。1.container {2width: 100%;3}4.left {5width: 50%; /* 容器宽度的50% */6float: left;7padding: 0 20px; /* 加上固定 padding 后总宽度超过50% */8}
解决方案:
box-sizing: border-box
(推荐):1* {2box-sizing: border-box; /* 全局应用 */3}
1.left {2width: calc(50% - 40px); /* 预留 padding 空间 */3padding: 0 20px;4}
1.container {2display: flex;3}4.left, .right {5flex: 1; /* 自动平均分配空间 */6padding: 0 20px;7}
box-sizing
:1html {2box-sizing: border-box;3}4*, *:before, *:after {5box-sizing: inherit;6}
确保元素尺寸计算更符合直觉。
min/max
限制:1.responsive-element {2width: 50%;3min-width: 300px; /* 防止在小屏幕上过窄 */4max-width: 600px; /* 防止在大屏幕上过宽 */5}
1.container {2display: grid;3grid-template-columns: 1fr 2fr 1fr; /* 比例布局比固定百分比更灵活 */4gap: 20px; /* 统一间距,避免百分比间距的问题 */5}
outline
(如 outline: 2px solid red
),避免 border
影响布局。background: rgba(255, 0, 0, 0.2)
)以可视化区域。rem
和 em
适合基于字体大小的调整,vw
和 vh
适合视口相关的设计。1.child {2width: 100%;3}