两种盒模型
CSS 的 box-sizing
属性控制盒模型类型:
- 标准盒模型(
content-box
) :width/height
仅表示内容区域的尺寸 - IE 盒模型(
border-box
) :width/height
表示内容 + padding + border的总和
假设设置以下样式:
css
.box {
width: 200px;
height: 100px;
padding: 20px;
border: 10px solid;
margin: 30px;
}
1. 标准盒模型
lua
+----------------------------------------+
| Margin (30px) |
| +----------------------------------+ |
| | Border (10px) | |
| | +----------------------------+ | |
| | | Padding (20px) | | |
| | | +----------------------+ | | |
| | | | Content (200px) | | | |
| | | +----------------------+ | | |
| | | | | |
| | +----------------------------+ | |
| | | |
| +----------------------------------+ |
+----------------------------------------+
- 总宽度 = 200 + 20 * 2 + 10 * 2 + 30 * 2 = 320px
2. IE盒模型
scss
+----------------------------------------+
| Margin (30px) |
| +----------------------------------+ |
| | Border (10px) + Padding (20px) | |
| | +----------------------------+ | |
| | | Content (实际: 140px) | | |
| | | (200 - 20*2 - 10*2 = 140) | | |
| | +----------------------------+ | |
| | | |
| +----------------------------------+ |
+----------------------------------------+
- 总宽度 = 200 + 30 * 2 = 260px
宽高属性详解
1.offsetWidth
/ offsetHeight
- 包含内容 :
width/height + padding + border
- 不包含 :
margin
例子:
content-box
:offsetWidth = 内容 + padding + border
宽: 200 + 20 * 2 + 10 * 2 = 260px
border-box
:offsetWidth = 设置的 width
200px
2. clientWidth
/ clientHeight
- 包含内容 :
width/height + padding
- 不包含 :
border
、margin
content-box
:clientWidth = 内容 + padding
200 + 20 * 2 = 240px
border-box
:clientWidth = 设置的 width - border
200 - 10*2 = 180px
3. getBoundingClientRect
getBoundingClientRect.width = (content + padding + border) * transform缩放系数
宽高与盒模型无关
- 作用 :返回元素相对于视口的精确几何信息
- 返回值 :一个
DOMRect
对象,包含 8 个属性:
js
{
x: // 元素左上角 X 坐标(等同 left)
y: // 元素左上角 Y 坐标(等同 top)
left: // 元素左侧到视口左侧的距离
top: // 元素顶部到视口顶部的距离
right: // 元素右侧到视口左侧的距离
bottom: // 元素底部到视口顶部的距离
width: // 元素的实际渲染宽度(含 transform)
height: // 元素的实际渲染高度(含 transform)
}
特性
特性 | 说明 |
---|---|
浮点精度 | 返回精确到亚像素级别的数值(如 100.25px) |
包含变换 | 计算 CSS transform(缩放/旋转/位移)后的实际渲染尺寸 |
视口相对 | 坐标基于当前可视区域(viewport),随滚动位置变化 |
实时计算 | 每次调用都会重新计算,可能触发重排(reflow) |
1.坐标系示意图
css
视口左上角 (0,0)
│
├──────────→ X轴
│
▼ Y轴
┌───────────────────────┐
│ 元素左上角 (left, top) │
│ │
│ width │
│ │
└───────────────────────┘
height
arduino
const rect = element.getBoundingClientRect();
rect.right === rect.left + rect.width
rect.bottom === rect.top + rect.height
2. 性能注意事项
- 避免频繁调用:会强制同步布局
- 批量读取:连续读取多个属性时只会触发一次重排
arduino
// (触发两次重排)
const width = el.getBoundingClientRect().width;
const height = el.getBoundingClientRect().height;
// (单次重排)
const rect = el.getBoundingClientRect();
const width = rect.width;
const height = rect.height;
4. scroll
1. scrollHeight & scrollWidth
scrollHeight = 内容实际高度 + padding
scrollWidth = 内容实际宽度 + padding
html
<div id="container" style="height:200px; overflow-y:scroll">
<div style="height:800px; padding:20px"></div>
</div>
<script>
console.log(container.scrollHeight); // 800 + 20*2 = 840
// 如果设置overflow-y:hidden,container.scrollHeight = 800 + 20 = 820
</script>
2. scrollTop & scrollLeft
图例
css
Content Area
↑
│ scrollTop
│
┌─┼──────────────────┐
│ │ │ ← 可视化区域
│ │ │
└─┴──────────────────┘
是否在底部
element.scrollTop >= scrollHeight - clientHeight
到达最右侧也是同理
element.scrollLeft >= scrollWidth - clientWidth
3. scrollTo方法
平滑滚动
less
// 原生平滑滚动
element.scrollTo({
top: 500,
behavior: 'smooth'
});
4. scrollTopMax / scrollLeftMax
目前只有火狐支持!
属性 | 描述 | 典型应用场景 |
---|---|---|
scrollTopMax |
最大可滚动距离 (scrollHeight - clientHeight ) |
检测是否滚动到底部 |
scrollLeftMax |
最大水平滚动距离 (scrollWidth - clientWidth ) |
横向滚动限制检测 |
兼容性对照表
属性/方法 | Chrome | Firefox | Safari | Edge | IE |
---|---|---|---|---|---|
scrollTopMax | ❌ | ✅ 44+ | ❌ | ❌ | ❌ |