CSS 布局概览

CSS 布局概览

7月 10, 2022
CSS, Frontend

越来越觉得,与其说 CSS 是编程语言,不如说它是配置文件。CSS (Cascading Style Sheets,层叠样式表)的诞生是为了图文信息展示服务的。CSS 布局机制通常就是指对 display 属性的设置,Display - MDN 文档指明 display 属性可以用来指示六种维度的值,下面就看看 display 设置了不同的值到底意味着什么。

盒子模型 #

先认识下通常说的盒子模型。

块级盒子 #

常见的诸如标题 (<h1>等) 和段落 (<p>) 默认情况下都是块级的盒子。块级盒子具有以下行为:

  • 每个元素都会换行
  • widthheight 将正常生效
  • paddingmarginborder 属性都会正常生效(将其他元素从当前盒子周围推开)

另外 CSS 中组成一个块级盒子需要:

  • margin(外边距)
  • border(边框)
  • padding(内边距)
  • content
    • width
    • height

在标准模型中,如果你给盒设置 widthheight,实际设置的是 content box。这一点很重要,因为这两个属性是“块级盒子”才能设置的。padding 和 border 再加上设置的宽高一起决定整个盒子的大小。如果有的时候我们不想这么计算,而是希望通过 widthheight 来设置整个盒子(即 border 包含的范围)的宽高,则可以通过 box-sizing 属性决定:

box-sizing: content-box; /* 标准模型 */
box-sizing: border-box; /* 替代模型 */

首先默认浏览器会使用标准模型,但是也可以自己设置为替代模型。尤其注意:border-box 不包含 margin

内联盒子 #

还有另一个叫内联盒子,内联盒子具有以下行为:

  • 不会产生换行
  • widthheight 将不产生作用
  • 垂直方向的 paddingmargin 以及 border 会被应用但是不会把其他处于 inline 状态的盒子推开
  • 水平方向的 paddingmargin 以及 border 会被应用且会把其他处于 inline 状态的盒子推开

Display 总览 #

每个元素都有两个盒子:外在盒子和内在盒子,外在盒子决定盒子是块级还是内联,内在盒子决定盒子内部元素是如何布局的。注意:内联和内部完全不是一个概念,相对应的外部也不是指块级盒子。也就是说不管块级还是内联指的都是外在盒子

我们通过对盒子 display 属性的设置,来控制盒子的外部显示类型和内部显示类型,下面会具体介绍,至此知道主要有外在和内在两个维度即可(实际上目前有六个维度),本篇文章的目录也可以清晰表示他们的关系。

<display-outside> 外在维度 #

<display-outside> - MDN

指定了元素的外部显示类型,实际上就是其在流式布局中的角色,即 block 还是 inline

block(块级元素) #

display: block 这个值会生成一个块级元素盒子,同时在该元素之前和之后打断(换行)。简单来说就是,这个值会将该元素变成块级元素。

严格地说,可能 display: block-block 会更形象。

inline(内联元素) #

这个值会生成一个行内元素盒子,该元素之前和之后不会打断(换行)。如果空间充足,该元素后的元素将会在同一行显示。简单来说就是,这个值会将该元素变成内联元素。

根据内外两个盒子的模型,那 inline 可能写作 display: inline-inline 会更形象。

由此可推,inline-block 就是外在的“内联”和内在的“块级盒子”组成的了。

用做链接的 <a> 元素、 <span><em> 以及 <strong> 都是默认处于 inline 状态的。

<display-inside> 内在维度 #

display-inside - MDN

下面的关键字指定了元素的内部显示类型,它们定义了该元素内部内容的布局方式。

flow(流式布局) #

CSS 原本的样子就是流式布局,是指在不对页面进行任何布局控制时,浏览器默认的 HTML 布局方式:一个个元素从左到右、从上到下根据 HTML 代码定义的内容顺序进行显示。

flow-root #

考虑兼容性可能比较新,可以先不了解。

table(表格布局) #

如果说 CSS 布局有第 0 代,就是表格 table 了。但是 <table> 标签比 CSS 还要老,在所讨论的所有的流式布局的世界中,都不包含 <table> ,关于 <table> 的内容以后单独再说,本文就不讨论了。

flex(弹性盒子布局) #

文档:CSS 弹性盒子布局 - MDN文档

练习游戏(玩一下就会了,讲了也是忘):

  1. http://www.flexboxdefense.com/
  2. https://flexboxfroggy.com/

这是一个例子:

#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; */
}

属性:

  1. justify-content(“横向”,取决于flex-direction)
    1. flex-start
    2. flex-end
    3. center
    4. space-between
    5. space-around
  2. align-items(“纵向”)
    1. flex-start
    2. flex-end
    3. center
  3. flex-direction
    1. row(默认)
    2. row-reverse
    3. column
    4. column-reverse
  4. align-self(子元素)
    1. flex-start
    2. flex-end
    3. center
  5. order(子元素)
    1. 可选 0,1,2,3 etc
  6. align-content
    1. 只适用多行的flex容器,也就是说子项不止一行时该属性才有效果
  7. flex-wrap
    1. 指定 flex 元素单行显示还是多行显示 。如果允许换行,这个属性允许你控制行的堆叠方向。
    2. nowrap(默认)
    3. wrap
    4. wrap-reverse

grid(网格布局) #

网格布局 - MDN 文档

练习游戏:

  1. https://cssgridgarden.com/

这是一个例子:

#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;
}

属性:

  1. grid-template-columns
  2. grid-template-rows
  3. grid-column-start(子元素)
  4. grid-column-end(子元素)
  5. grid-column(等价于 3+4)
  6. grid-row-start(子元素)
  7. grid-row-end(子元素)
  8. grid-row(6+7)
  9. grid-area(等价于 row-start/column-start/row-end/column-end)
  10. order(元素间的排序)
  11. grid-template(1+2),中间要有斜线。

ruby #

类似于 <ruby> 标签的特性,被用来展示东亚文字注音或字符注释,暂无需求本文先不讨论了。

<display-listitem> #

值为 list-item 类似 ulli 标签一样的样式,可以使用 list-style-typelist-style-position 选项进行装饰。

<display-box> #

这些关键词定义一个元素到底是否产生显示盒(display boxes):

  • contents
  • none

display 的 none 值比较常用,它会关闭元素的显示,且不影响布局(就当作文件中没有该元素)。

要一个元素占据空间(文件中存在),但不渲染,请使用 visibility 属性。

<display-internal> #

一些布局模型(如 table 和 ruby)具有复杂的内部结构,暂不了解。

<display-legacy> #

CSS 2 对 display 属性使用了单关键字语法,对于相同布局模式的块级和内联级的变体,需要单独的关键字。

inline-block #

除了完全的 block-blockinline-inline 之外,还有一个就是 inline-block,它可以有以下能力:

  • 设置 widthheight 属性会生效。
  • paddingmargin 以及 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 属性用于指定一个元素在文档中的定位方式。toprightbottomleft 属性则决定了该元素的最终位置。它的取值枚举有以下几种。

  • static
  • relative
  • absolute
  • fixed
  • sticky

参考 #

CSS - MDN

CSS 布局 - MDN

CSS 世界(这本书基本就全在讲布局体系)

本文共 2816 字,上次修改于 Jul 9, 2024,以 CC 署名-非商业性使用-禁止演绎 4.0 国际 协议进行许可。

相关文章

» CSS 选择器语法举例

» AJAX 是什么?

» 浏览器的事件机制

» 搞懂原型链

» WebSocket 是什么?