CSS 布局概览
7月 10, 2022
越来越觉得,与其说 CSS 是编程语言,不如说它是配置文件。CSS (Cascading Style Sheets,层叠样式表)的诞生是为了图文信息展示服务的。CSS 布局机制通常就是指对 display 属性的设置,Display - MDN 文档指明 display 属性可以用来指示六种维度的值,下面就看看 display 设置了不同的值到底意味着什么。
盒子模型#
先认识下通常说的盒子模型。
块级盒子#
常见的诸如标题 (<h1>等) 和段落 (<p>) 默认情况下都是块级的盒子。块级盒子具有以下行为:
- 每个元素都会换行
width和height将正常生效padding、margin、border属性都会正常生效(将其他元素从当前盒子周围推开)
另外 CSS 中组成一个块级盒子需要:
- margin(外边距)
- border(边框)
- padding(内边距)
- content
- width
- height

在标准模型中,如果你给盒设置 width 和 height,实际设置的是 content box。这一点很重要,因为这两个属性是“块级盒子”才能设置的。padding 和 border 再加上设置的宽高一起决定整个盒子的大小。如果有的时候我们不想这么计算,而是希望通过 width 和 height 来设置整个盒子(即 border 包含的范围)的宽高,则可以通过 box-sizing 属性决定:
box-sizing: content-box; /* 标准模型 */
box-sizing: border-box; /* 替代模型 */首先默认浏览器会使用标准模型,但是也可以自己设置为替代模型。尤其注意:border-box 不包含 margin。
内联盒子#
还有另一个叫内联盒子,内联盒子具有以下行为:
- 不会产生换行
width和height将不产生作用- 垂直方向的
padding、margin以及border会被应用但是不会把其他处于inline状态的盒子推开 - 水平方向的
padding、margin以及border会被应用且会把其他处于inline状态的盒子推开
Display 总览#
每个元素都有两个盒子:外在盒子和内在盒子,外在盒子决定盒子是块级还是内联,内在盒子决定盒子内部元素是如何布局的。注意:内联和内部完全不是一个概念,相对应的外部也不是指块级盒子。也就是说不管块级还是内联指的都是外在盒子。
我们通过对盒子 display 属性的设置,来控制盒子的外部显示类型和内部显示类型,下面会具体介绍,至此知道主要有外在和内在两个维度即可(实际上目前有六个维度),本篇文章的目录也可以清晰表示他们的关系。
<display-outside> 外在维度#
指定了元素的外部显示类型,实际上就是其在流式布局中的角色,即 block 还是 inline 。
block(块级元素)#
display: block 这个值会生成一个块级元素盒子,同时在该元素之前和之后打断(换行)。简单来说就是,这个值会将该元素变成块级元素。
严格地说,可能
display: block-block会更形象。
inline(内联元素)#
这个值会生成一个行内元素盒子,该元素之前和之后不会打断(换行)。如果空间充足,该元素后的元素将会在同一行显示。简单来说就是,这个值会将该元素变成内联元素。
根据内外两个盒子的模型,那
inline可能写作display: inline-inline会更形象。由此可推,inline-block就是外在的“内联”和内在的“块级盒子”组成的了。
用做链接的 <a> 元素、 <span>、 <em> 以及 <strong> 都是默认处于 inline 状态的。
<display-inside> 内在维度#
下面的关键字指定了元素的内部显示类型,它们定义了该元素内部内容的布局方式。
flow(流式布局)#
CSS 原本的样子就是流式布局,是指在不对页面进行任何布局控制时,浏览器默认的 HTML 布局方式:一个个元素从左到右、从上到下根据 HTML 代码定义的内容顺序进行显示。
flow-root#
考虑兼容性可能比较新,可以先不了解。
table(表格布局)#
如果说 CSS 布局有第 0 代,就是表格 table 了。但是 <table> 标签比 CSS 还要老,在所讨论的所有的流式布局的世界中,都不包含 <table> ,关于 <table> 的内容以后单独再说,本文就不讨论了。
flex(弹性盒子布局)#
练习游戏(玩一下就会了,讲了也是忘):
这是一个例子:
#parent {
display: flex;
flex-flow: column wrap; /*(direction+wrap)*/
flex-wrap: nowrap; /* wrap; wrap-reverse; */
flex-direction: row; /* column; row-reverse; column-reverse; */
align-items: flex-start;
align-content: flex-start;
justify-content: flex-start;
justify-items: flex-start;
}
#child {
order: 1; /* 默认为 0 */
align-self: flex-start; /* flex-end;center; */
}属性:
- justify-content(“横向”,取决于 flex-direction)
- flex-start
- flex-end
- center
- space-between
- space-around
- align-items(“纵向”)
- flex-start
- flex-end
- center
- flex-direction
- row(默认)
- row-reverse
- column
- column-reverse
- align-self(子元素)
- flex-start
- flex-end
- center
- order(子元素)
- 可选 0,1,2,3 etc
- align-content
- 只适用多行的 flex 容器,也就是说子项不止一行时该属性才有效果
- flex-wrap
- 指定 flex 元素单行显示还是多行显示 。如果允许换行,这个属性允许你控制行的堆叠方向。
- nowrap(默认)
- wrap
- wrap-reverse
grid(网格布局)#
练习游戏:
这是一个例子:
#garden {
display: grid;
grid-template-columns: 20% 20% 20% 20% 20%;
grid-template-rows: 20% 20% 20% 20% 20%;
grid-template-columns: repeat(1, 12.5%);
grid-template-columns: 1fr 5fr; /*(fractional 分数)*/
grid-template: 60% 40% / 200px;
}
#watch {
grid-column-start: 1;
grid-column-end: 2;
grid-column: 1/2;
grid-column-start: 1;
grid-column-end: span 2;
grid-area: 1 / 4 / 6 / 5;
}属性:
- grid-template-columns
- grid-template-rows
- grid-column-start(子元素)
- grid-column-end(子元素)
- grid-column(等价于 3+4)
- grid-row-start(子元素)
- grid-row-end(子元素)
- grid-row(6+7)
- grid-area(等价于 row-start/column-start/row-end/column-end)
- order(元素间的排序)
- grid-template(1+2),中间要有斜线。
ruby#
类似于 <ruby> 标签的特性,被用来展示东亚文字注音或字符注释,暂无需求本文先不讨论了。
<display-listitem>#
值为 list-item 类似 ul、 li 标签一样的样式,可以使用 list-style-type 和 list-style-position 选项进行装饰。
<display-box>#
这些关键词定义一个元素到底是否产生显示盒(display boxes):
- contents
- none
display 的 none 值比较常用,它会关闭元素的显示,且不影响布局(就当作文件中没有该元素)。
要一个元素占据空间(文件中存在),但不渲染,请使用 visibility 属性。
<display-internal>#
一些布局模型(如 table 和 ruby)具有复杂的内部结构,暂不了解。
<display-legacy>#
CSS 2 对 display 属性使用了单关键字语法,对于相同布局模式的块级和内联级的变体,需要单独的关键字。
inline-block#
除了完全的 block-block 和 inline-inline 之外,还有一个就是 inline-block,它可以有以下能力:
- 设置
width和height属性会生效。 padding、margin以及border会推开其他元素。
inline-table#
等效于 inline table
inline-flex#
等效于 inline flex
inline-grid#
等效于 inline grid
小结#
See the Pen Untitled by tcitry (@tcitry) on CodePen.
上面 这个例子(来自 MDN )可以多尝几遍。最后,看完上面的宏观分类以后,知道了 display 的使用场景,下面针对常用每个微观领域进行描述。
可见仅仅是关于布局的属性也非常多,没必要都记住,本文也无意要区分各个相近名称的区别,真正要做的是能够清晰分类,在需要的时候通过快速查阅文档找到需要的属性,然后再通过一些 demo 来快速验证。
其他布局方式#
其他脱离了 display 系统的布局方式。
传统布局#
就是 width + float
https://developer.mozilla.org/zh-CN/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods
多列布局#
column-count
column-width
https://developer.mozilla.org/zh-CN/docs/Learn/CSS/CSS_layout/Multiple-column_Layout
浮动 Float#
float CSS 属性指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。该元素从网页的正常流动(文档流)中移除,尽管仍然保持部分的流动性(与绝对定位相反)。由于 float 意味着使用块布局,它在某些情况下会修改 display 值的计算值。
它有以下几种枚举:
- left
- right
- none:
- inline-start
- inline-end
定位 Position#
CSS position 属性用于指定一个元素在文档中的定位方式。top,right,bottom 和 left 属性则决定了该元素的最终位置。它的取值枚举有以下几种。
- static
- relative
- absolute
- fixed
- sticky
参考#
CSS 世界(这本书基本就全在讲布局体系)