1. 盒子水平方向过度约束
1.1 过度约束的定义
过度约束是浏览器的一种渲染规则 / 机制,针对元素水平方向的 7 个属性值:margin-left、border-left、padding-left、width、padding-right、border-right、margin-right。
这 7 个属性值相加必须等于其父元素内容区的宽度 ,若不相等,浏览器会自动强制调整其中的margin(左右外边距)或width(内容区宽度),以实现两者全等。
1.2 浏览器调整规则
浏览器的调整逻辑完全取决于这 7 个值中是否存在auto(仅margin-left、width、margin-right可被设置为auto),具体分为以下几种情况:
- 无
auto的情况 若 7 个属性值中没有任何一个被设置为auto,浏览器默认调整margin-right,通过改变其值来满足总宽度等于父元素内容区宽度的要求。 - 1 个
auto的情况 哪个属性被设置为auto,就自动调整哪个属性的值,使其满足总宽度匹配的约束。 - 2 个
auto的情况- 当
margin-left和width为auto:优先调整width - 当
width和margin-right为auto:优先调整width - 当
margin-left和margin-right为auto:两个外边距各调整一半,最终将元素水平居中显示
- 当
- 3 个
auto的情况 若margin-left、width、margin-right均为auto,浏览器仅调整width,使其满足宽度约束。
1.3 核心总结
- 水平方向 7 个值无
auto:默认调整margin-right - 若
width为auto:无论其他属性是否为auto,优先只调整width - 若
width为固定值,且margin-left、margin-right均为auto:左右外边距各调整一半,实现盒子水平居中
2. 垂直外边距的重叠
元素垂直方向的外边距(margin-top、margin-bottom)不会叠加生效,而是会发生重叠,主要分为兄弟元素 和父子元素两种场景。
2.1 兄弟元素垂直外边距重叠
兄弟元素的上元素margin-bottom(下外边距)和下元素margin-top(上外边距)会重叠在一起,最终生效的外边距按以下规则计算:
- 两者均为正值:取较大的那个值作为最终生效的外边距
- 两者均为负值:取绝对值较大的那个值作为最终生效的外边距(负值保留,仅绝对值比较)
- 一正一负:取两者的和作为最终生效的外边距
注意:兄弟元素的垂直外边距重叠是正常渲染效果,一般无需额外处理。
2.2 父子元素垂直外边距重叠(外边距传递)
2.2.1 重叠现象
若父子元素的垂直外边距直接相邻(父元素无边框、无内边距、无 BFC 特性),子元素的垂直外边距会传递给父元素,导致父元素随子元素的外边距一起偏移,无法实现子元素在父元素内的顶部 / 底部间距效果。
2.2.2 解决方案
方案 1:开启父元素 BFC(推荐)
给父元素设置overflow属性,值为非visible(默认值)即可开启 BFC(块级格式化上下文)。BFC 会让父元素成为一个独立的渲染区块,不受子元素外边距的影响,阻断外边距传递。
css
.parent {
/* 任意非visible的值均可,常用hidden */
overflow: hidden;
/* 也可使用auto、scroll等 */
/* overflow: auto; */
}
方案 2:给父元素设置透明边框
给父元素设置一层透明边框,隔开父子元素的垂直外边距,避免直接相邻,从而阻止外边距传递。
css
.parent {
/* 透明边框,不影响视觉效果,仅阻断外边距重叠 */
border: 1px solid transparent;
}
方案 3:使用伪元素清除(通用类名)
定义一个通用类名(如clearfix),通过伪元素::before创建空内容并转换为表格类型,隔开父子元素的外边距,可复用在任意需要解决该问题的父元素上。
css
/* 通用清除父子外边距重叠的类 */
.clearfix::before {
content: ''; /* 增加空内容 */
display: table; /* 将空内容转换为空表格,阻断外边距传递 */
}
/* 使用方式:给父元素添加clearfix类即可 */
/* <div class="parent clearfix">...</div> */
3. 补充:盒子相关基础回顾
3.1 盒子各区域特性
- 内容区 :无法自定义大小,默认由子元素或文本内容撑开;默认情况下
width、height属性控制的是内容区大小 - 内边距(padding):可自定义大小,垂直方向不会挤压其他元素位置,仅会覆盖其他元素,同时会扩大盒子的可见大小
- 边框(border):可自定义大小、颜色、样式,属于盒子可见部分,会扩大盒子的可见大小
- 外边距(margin):水平方向可设置且会叠加生效;垂直方向设置后可能发生重叠,不影响盒子自身大小,仅控制元素间的距离
3.2 盒子尺寸计算方式(box-sizing)
box-sizing用于设置盒子width/height的控制范围,可选值如下:
content-box:默认值,width/height仅控制内容区大小,盒子可见大小 = 内容区 + 内边距 + 边框border-box:width/height控制整个盒子的可见大小(包含内容区、内边距、边框),方便精准控制盒子尺寸,是布局常用值
css
.box {
box-sizing: border-box;
width: 200px; /* 该宽度包含content + padding + border */
padding: 20px;
border: 1px solid #000;
}
3.3 重置样式表
3.3.1 为什么需要重置样式表
浏览器会为部分元素设置默认的margin和padding(如body默认有上下外边距、ul默认有左侧内边距),这些默认样式会影响布局效果,因此编写样式前通常需要重置默认样式。
3.3.2 常用重置样式表及区别
目前主流的重置样式表有两种:reset.css 和 Normalize.css,二者均解决浏览器默认样式的兼容性问题,核心区别如下:
reset.css:采用 "清零" 策略,将所有元素的默认margin、padding及其他默认样式全部去除,后续样式完全由程序员自定义Normalize.css:不清除默认样式,仅统一不同浏览器对相同元素的默认样式解析差异,保留元素的默认视觉效果,更符合浏览器原生渲染逻辑
3.3.3 引入方式
html
<!-- 先引入重置样式表 -->
<link rel="stylesheet" href="./reset.css" />
<!-- 再引入自定义样式表(自定义样式会覆盖重置样式) -->
<link rel="stylesheet" href="./index.css" />