CSS 零基础教程

CSS 文档流原理

普通流 (Normal Flow),也称为文档流 (Document Flow),是 HTML 元素在网页上默认的显示方式。

如果不了解元素在自然状态下的行为方式,就很难有效地控制和操作它们的位置。

本章将探讨普通流的原理、特点及其局限性,为学习更高级的布局方法(如定位、FlexboxGrid)打下基础。

1. 理解普通流

普通流决定了在没有应用其他布局机制时,元素如何在网页上渲染。这是浏览器显示 HTML 元素的默认方式。

普通流的关键特征包括:

  • 块级元素 (Block-level elements): 这些元素(如 <div>、<p>、<h1>-<h6>、<form><ul>)会占据其可用的全部宽度(除非受到父元素宽度的限制),并且垂直堆叠,一个接一个。每个块级元素都从新的一行开始。
  • 行内元素 (Inline elements): 这些元素(如 <span>、<a>、<img>、<strong><em>)只占据包含其内容所需的宽度。它们在包含块内水平流动,就像句子中的单词一样。如果空间不足,它们会换行到下一行。
  • 内容顺序: 元素按照它们在 HTML 源代码中出现的顺序显示。浏览器从上到下读取 HTML 并相应地渲染元素。
  • 外边距合并 (Margin collapsing): 块级元素之间的垂直外边距可能会合并,意味着只有两个外边距中较大的那个会被应用。这种行为有时会出乎意料,但它是普通流的一个标准特性。

2. 块级元素 (Block-Level Elements) 详解

块级元素总是从新的一行开始,并延伸以填满其父容器的宽度。

让我们看一个例子:

<div>这是一个块级元素。</div>
<div>这是另一个块级元素</div>

在这种情况下,每个 <div> 将占据其父元素(通常是 <body>)的全部宽度,并垂直堆叠。如果你在浏览器的开发者工具中检查这一点,你会看到每个 div 的宽度延伸到了浏览器窗口的边缘(或其包含元素的边缘)。

你可以使用 CSS 中的 width 属性控制块级元素的宽度。例如:

div {
  width: 50%;
  background-color: lightblue;
}

这将使每个 <div> 只占据父元素宽度的 50%,但它们仍然会垂直堆叠(独占一行)。

<p>这是一个段落包含 <span>一个行内元素</span> 在里面。</p>

<span> 元素将简单地在段落内流动,就像任何其他单词一样。它不会从新的一行开始,也不会强制周围的文本换行。

你可以对行内元素应用 CSS,但某些属性(如 widthheight没有任何效果。要控制行内元素的尺寸,你可以将其 display 属性更改为 inline-block

3. display 属性:块与行内之间的桥梁

display 属性对于理解普通流以及如何修改它至关重要。它决定了元素的渲染框类型。

最常见的值有:

  • block: 元素表现得像块级元素。
  • inline: 元素表现得像行内元素。
  • inline-block: 元素作为行内元素放置(可以和其他元素并排),但表现得像块级元素,允许你设置宽度和高度。
  • none: 元素根本不显示,并且在文档中不占据任何空间。

inline-block 值特别有用,当你想要控制元素的尺寸,同时仍希望它与其他内容行内流动时。例如:

<a href="#" class="button">点击我</a>
<a href="#" class="button">另一个按钮</a>
.button {
  display: inline-block;
  width: 100px;
  height: 30px;
  background-color: #4CAF50;
  color: white;
  text-align: center;
  text-decoration: none;
  line-height: 30px; /* 垂直居中文本 */
  border-radius: 5px;
}

在这个例子中,<a> 元素被样式化为 inline-block,允许你设置它们的宽度和高度,同时让它们彼此水平相邻流动。

4. 外边距合并 (Margin Collapsing) 详解

外边距合并 是 CSS 中的一种行为,即相邻块级元素的顶部和底部外边距有时会合并成一个单一的外边距,其大小等于两个外边距中最大的那个。

考虑以下 HTML:

<div style="margin-bottom: 20px; background-color: lightcoral;">第一个 div</div>
<div style="margin-top: 30px; background-color: lightgreen;">第二个 div</div>

你可能预期两个 div 元素之间的间距是 50px (20px + 30px)。然而,由于外边距合并,实际间距将是 30px(两个外边距中较大的那个)。

外边距合并仅发生在相邻块级元素的垂直外边距上。它不会发生在:

  • 水平外边距
  • 行内元素的外边距
  • 浮动元素的外边距
  • 绝对定位元素的外边距
  • 被非空内容、内边距 (padding) 或边框 (border) 分隔的外边距

理解外边距合并对于预测和控制普通流中元素之间的间距非常重要。

5. 普通流的局限性

虽然普通流为显示内容提供了基本结构,但在创建复杂布局时,它有几个局限性:

  1. 对定位的控制有限: 普通流主要规定了垂直堆叠和水平流动。它几乎不提供对元素精确位置的控制。
  2. 难以创建多列布局: 仅使用普通流很难创建包含多列内容的布局。你通常需要使用浮动 (floats) 或其他更高级的技术。
  3. 响应式挑战: 使得布局适应不同屏幕尺寸在普通流中可能很困难。元素可能无法在较小的屏幕上按预期重新流动或调整大小。
  4. 缺乏对齐选项: 普通流提供的元素对齐选项有限,尤其是垂直对齐。

5.1 普通流布局困难的例子

想象一下,你想创建一个简单的布局,包含一个页头、左侧的一个侧边栏和右侧的主要内容。

仅使用普通流,这很难实现。侧边栏和主要内容自然会垂直堆叠,而不是并排坐落。

为了克服这些限制,CSS 提供了其他布局技术,如定位 (Positioning)FlexboxGrid