CSS 盒模型
在 css 中, 所有元素都被一个个的 "box" 包围着, 理解这些盒子的基本原理, 是实现用 css 实现精准布局, 处理元素排列的关键.
标准盒模型
盒子模型的组成元素:
- content: 内容区
- padding: 内天成
- border: 边框
- margin: 外边距
在标准盒模型中, 盒的 width / height
指的是内容区域 content-box
标准盒模型尺寸 = content-box + padding + border
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>css-box</title>
<style>
.box1 {
width: 100px;
height: 100px;
padding: 20px;
border: 10px solid gray;
margin: 20px;
background-color: pink;
}
.box2 {
width: 100px;
height: 100px;
background-color: skyblue;
margin-top: -40px;
}
</style>
</head>
<body>
<div class="box1">box1</div>
<div class="box2">box2</div>
</body>
</html>
这里的, padding, margin, boder 都可以单独写方向, 如 top, right, bottom, left .
- 1个值, padding: 10px; 表示上下左右都是 10px 的内间距
- 2个值, margin: 5px 10px; 表示上下外边距 5px, 左右外边距 10px
- 3个值, 根本记不住, 不如直接写4个得了
- 4个值, margin: 1px 2px 3px 4px; 按适中顺序来的, 表示 上, 右, 下, 左的外边距分别为 1px, 2px, 3px, 4px
盒模型的注意点:
- padding 不能为负值, 而 margin 可以为负值, 就往上移动了.
- 背景色会平铺到非 margin 的区域
- margin-top 会出现 "传递" 的现象
- margin 上下叠加会出现 "塌陷"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>css-box</title>
<style>
.box1 {
width: 200px;
height: 200px;
background-color: pink;
}
.box2 {
width: 100px;
height: 100px;
background-color: skyblue;
/* 嵌套时, margin-top 会传递父容器 */
margin-top: 30px;
/* border-top: 30px solid #ccc; */
}
</style>
</head>
<body>
<div class="box1">
<div class="box2"></div>
</div>
</body>
</html>
这里的 box2 因为有了 margin-top
会将其传染到父元素 box1, 导致整块进行了上移, 就很难受. 解决办法呢, 可以改用 padding , 或者 加一个透明边框 或者让其形成 BFC 等, 但最终解决方案还是用 flex / grid
布局搞定一切.
/* border-top: 30px solid #ccc; */
margin-top: 30px;
关于 margin 塌陷
也是经常出现的现象, 比如有上下两个盒子 box1, box2.
给 box1 的外下边距设置 30px, 给 box2 的外上边距设置 40px
发现这两个上下盒子的距离不是 30 + 40 = 70px, 而是二者取其大为 40px, 这就是所谓的 "margin 塌陷"
当然这种现象只会出现在上下布局中, 左右不影响, 解决方法通常可以是 margin 只设置在一头就行
, 或者用 BFC 也行, 当然最终推荐还需是 flex / grid.
块级盒子 与 内联盒子
在 css 中我们广泛使用两种盒子, 即块级盒子和内联盒子, 他们在页面中表现的行为方式是不同的.
- 块级盒子: div, p, h1 ...
- 内联盒子: span, a, strong ..
块级盒子 | 内联盒子 | |
---|---|---|
占行 | 独占一行 | 不产生换行 |
样式 | 支持所有样式 | 有些样式不支持, 如 width, height, margin 仅支持左右等 |
宽度 | 不写宽度的时候, 跟父容器同宽 | 不写宽度的时候, 宽度由内容决定 |
区域 | 所占区域是一个矩形 | 所占区域不一定是矩形, 如内容多了会自动换行 |
间隙 | 盒子间无间隙 | 内联标签之间会有间隙 |
对比指向发现内联盒子的问题特别多, 就咱在做布局的时候尽量不要选它哦, 内联盒子更多作为修饰而已啦.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>块级/内联盒子</title>
<style>
.box1 {
/* 块级盒子不写宽时, 会与其父元素(此时为 body) 同宽 */
/* width: 100px; */
height: 100px;
background-color: pink;
}
.box2 {
width: 100px;
height: 100px;
background-color: skyblue;
}
.inline1 {
background-color: pink;
/* 内联盒子不支持宽高, margin 只支持左右 */
width: 100px;
height: 100px;
}
.inline2 {
background-color: skyblue;
}
</style>
</head>
<body>
<!-- div 是块盒子, 会默认上下排列 -->
<div class="box1">块级盒子1</div>
<div class="box2">块级盒子2</div>
<span class="inline1">内联盒子1</span>
<span class="inline2">内联盒子2内联盒子2内联盒子2内联盒子2内联盒子2内联盒子2内联盒子2内联盒子2内联盒子2</span>
</body>
</html>
自适应盒模型
自适应盒模型是指, 当盒子不设宽度时, 盒模型相关组成部分的处理方式是怎样的.
即一个小技巧是, 子盒子不设宽度, 它会默认同父元素, 同时内容也会自动往里缩
.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>自适应盒模型</title>
<style>
.box1 {
width: 300px;
height: 200px;
background-color: pink;
}
/* .box2 {
width: 300px;
height: 100px;
background-color: skyblue;
padding: 10px;
border: 5px solid gray;
margin: 10px;
} */
.box2 {
/* 当子盒子不写宽度时, 会保持与父元素同宽, 内容缩小 */
/* width: 300px; */
height: 100px;
background-color: skyblue;
/* 盒子和溢出 */
padding: 10px;
border: 5px solid gray;
margin: 10px;
}
</style>
</head>
<body>
<!-- 嵌套块盒子会溢出 -->
<div class="box1">
<div class="box2">box2</div>
</div>
</body>
</html>
而千万不要去各种计算 content 啥的啦. 当然子盒子的内容如果有很多很多也不会撑开盒子宽, 会进行换行, 浮在图层上溢出啥的.
标准盒模型 与 怪异盒模型
就二者的计算宽高方式不一样而已, 推荐后者.
- 标准盒模型
width: 100px
: 只包content-box
, 不包含 padding + border - 怪异盒模型
width: 100px
: 总包content-box + padding + border
怪异盒模型其实更偏向于我们的认知直觉, 尤其是页面布局划分区域块的时候, 核心就是这一句:
/* 怪异盒模型下, content 会被 width 进行内缩 */
box-sizing: border-box;
box-sizing
的默认值是 content-box
, 然后一旦改成 border-box
就变成怪异盒模型啦.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>标准/怪异模型</title>
<style>
.box1 {
width: 100px;
height: 100px;
background-color: pink;
/* 标准盒模型下, padding, border 会对 content 进行扩散 */
/* 此时的尺寸是, 100 + 10 * 2 + 10*2 = 140px 宽高的的盒子区域*/
padding: 10px;
border: 10px solid gray;
}
.box2 {
width: 100px;
height: 100px;
background-color: pink;
/* 怪异盒模型下, content 会被 width 进行内缩 */
box-sizing: border-box;
/* 此时的尺寸是, 还是 100px宽高的的盒子, 内容区缩成 60x60 啦 */
padding: 10px;
border: 10px solid gray;
}
</style>
</head>
<body>
<!-- 标准盒模型, width 只包 content -->
<div class="box1"></div>
<!-- 怪异盒模型, width 全包 content + padding + margin -->
<div class="box2"></div>
</body>
</html>
怪异盒模型的一个重要应用, 是在量区尺寸的时候, 不用再去计算一些值, 直接测出某区域的尺寸, 让内容往里面缩即可, 即先整体, 再局部.
其次是在解决一些需要设置百分比的时候比较方便.
尤其是在移动端的时候, 改成怪异盒模型布局能有效防止元素的溢出, 避免出现滚动条之类的.
基础的盒模型认知到这里就差不多啦.