CSS 盒模型、布局和包含块

3,217 阅读6分钟

CSS 基础盒模型

CSS 盒模型是页面布局的基础。

当对一个文档进行布局的时候,浏览器的渲染引擎会根据标准之一的 CSS 基础框盒模型(CSS basic box model),将所有元素表示为一个个矩形的盒子(box)。CSS 决定这些盒子的大小、位置以及属性(例如颜色、背景、边框尺寸…)。

每个盒子由四个部分(或称区域)组成,分别为:内容区域 content area内边距区域 padding area边框区域 border area外边距区域 margin area,分别对应 width、heightpaddingbordermargin

注意 box-sizing 这个 CSS 属性。

  1. content-box (W3C 盒模型)是默认值。如果你设置一个元素的宽为 100px,那么这个元素的内容区会有 100px 宽,并且任何边框和内边距的宽度都会被增加到最后绘制出来的元素宽度中。也就是说,最终盒子的宽高 >= 设置的宽高
  2. border-box (IE 盒模型)告诉浏览器:你想要设置的边框和内边距的值是包含在 width 内的。也就是说,如果你将一个元素的 width 设为 100px,那么这 100px 会包含它的 borderpadding,内容区的实际宽度是 width 减去(border + padding)的值。大多数情况下,这使得我们更容易地设定一个元素的宽高。

看下面的例子。

<div class="content-box">Content box</div>
<br>
<div class="border-box">Border box</div>
div {
  width: 160px;
  height: 80px;
  padding: 20px;
  border: 8px solid red;
  background: yellow;
}

.content-box { 
  box-sizing: content-box; 
  /* Total width: 160px + (2 * 20px) + (2 * 8px) = 216px
     Total height: 80px + (2 * 20px) + (2 * 8px) = 136px
     Content box width: 160px
     Content box height: 80px */
}

.border-box { 
  box-sizing: border-box;
  /* Total width: 160px
     Total height: 80px
     Content box width: 160px - (2 * 20px) - (2 * 8px) = 104px
     Content box height: 80px - (2 * 20px) - (2 * 8px) = 24px */
}

盒模型

从结果可以看得比较明白,border-box 的总宽高不会超过设定的 widthheight,而 content-box 的大小是不确定的,会受到 borderpadding 影响。

布局和包含块

元素的尺寸及位置,常常会受它的包含块所影响。对于一些属性,例如 width, height, padding, margin,绝对定位元素的偏移值 (比如 position 被设置为 absolutefixed),当我们对其赋予百分比值时,这些值的计算值,就是通过元素的包含块计算得来。

position

确定一个元素的包含块的过程完全依赖于这个元素的 position 属性。我们先看看 position 属性。

  1. static 该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时 top, right, bottom, leftz-index 属性无效。
  2. relative 该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。position:relativetable-*-group, table-row, table-column, table-cell, table-caption 元素无效。
  3. absolute 不为元素预留空间,通过指定元素相对于最近的非 static 定位祖先元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。
  4. fixed 不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed 属性会创建新的层叠上下文。当元素祖先的 transform 属性非 none 时,容器由视口改为该祖先
  5. sticky 盒位置根据正常流计算(这称为正常流动中的位置),然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。在所有情况下(即便被定位元素为 table 时),该元素定位均不对后续元素造成影响。当元素 B 被粘性定位时,后续元素的位置仍按照 B 未定位时的位置来确定。position: sticky 对 table 元素的效果与 position: relative 相同。 粘性定位可以被认为是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位。 它可以很方便的实现 IOS 中的列表 title 吸顶效果。
  <head>
    <style>
      #box {
        height: 5000px;
      }
      #sti {
        position: sticky;
        top: 100px;
      }
      p {
        height: 1000px;
      }
    </style>
  </head>
  <body>
    <div id="box" class="box1" name="lxfriday">
      <p>hello div</p>
      <div id="sti">sti</div>
    </div>
  </body>

确定包含块

确定一个元素的包含块的过程完全依赖于这个元素的 position 属性:

  1. 如果 position 属性为 staticrelative ,包含块就是由它的最近的祖先块元素(inline-blockblocklist-item),或者 BFC(tableflexgrid) 的内容区的边缘组成的。
  2. 如果 position 属性为 absolute ,包含块就是由它的最近的 position 的值不是 static (也就是值为fixed, absolute, relativesticky)的祖先元素的内边距区的边缘组成。
  3. 如果 position 属性是 fixed,可以认为包含块就是视口 viewport。

注意: 根元素(<html>)所在的包含块是一个被称为初始包含块的矩形,可认为是视口 viewport。.

根据包含块计算百分值

如果某些属性被赋予一个百分值的话,它的计算值是由这个元素的包含块计算而来的。这些属性包括盒模型属性偏移属性

  1. 要计算 height topbottom 中的百分值,是通过包含块的 height 的值。如果包含块的 height 值会根据它的内容变化,而且包含块的 position 属性的值被赋予 relativestatic ,那么,这些值的计算值为 0,也就是说包含块自身能先确定高度才可以让子元素的百分比计算生效。

    看下面例子, .con 这个父元素没有设置高度, .c1 子元素设置了高度 500px.c2 设置的是百分比高度,根据上面的规则, 由于父元素 .conpositionstatic,所以子元素设置百分比高度将会无效。

<head>
<style>
    .con {
      background-color: red;
    }
    .c1 {
      background-color: cyan;
      height: 500px;
    }
    .c2 {
      background-color: green;
      height: 100%;
    }
  </style>
  </head>
  <body>
    <div class="con">
      <div class="c1"></div>
      <div class="c2"></div>
    </div>
  </body>
  1. 要计算 width, left, right, padding, margin 这些属性由包含块的 width 属性的值来计算它的百分值。

感谢阅读,欢迎关注我的公众号 云影sky,带你解读前端技术。

公众号

参考:

  1. CSS 基础框盒模型介绍
  2. 布局和包含块