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>

怪异盒模型的一个重要应用, 是在量区尺寸的时候, 不用再去计算一些值, 直接测出某区域的尺寸, 让内容往里面缩即可, 即先整体, 再局部.

其次是在解决一些需要设置百分比的时候比较方便.

尤其是在移动端的时候, 改成怪异盒模型布局能有效防止元素的溢出, 避免出现滚动条之类的.

基础的盒模型认知到这里就差不多啦.

posted @ 2024-05-05 17:54  致于数据科学家的小陈  阅读(26)  评论(0编辑  收藏  举报