CSS 布局简介

本文将回顾我们在之前的模块中已经接触过的一些 CSS 布局功能,例如不同的 display 值,并介绍我们将在本模块中涵盖的一些概念。

¥This article will recap some of the CSS layout features we've already touched upon in previous modules, such as different display values, as well as introduce some of the concepts we'll be covering throughout this module.

先决条件: HTML 基础知识(学习 HTML 简介),以及 CSS 工作原理的概念(学习 CSS 简介)。
目标: 为你提供 CSS 页面布局技术的概述。每种技术都可以在后续教程中更详细地学习。

CSS 页面布局技术允许我们获取网页中包含的元素并根据以下因素控制它们的位置:它们在正常布局流中的默认位置、它们周围的其他元素、它们的父容器和主视口/窗口。我们将在本模块中更详细地介绍的页面布局技术是:

¥CSS page layout techniques allow us to take elements contained in a web page and control where they're positioned relative to the following factors: their default position in normal layout flow, the other elements around them, their parent container, and the main viewport/window. The page layout techniques we'll be covering in more detail in this module are:

  • 正常流量
  • display 属性
  • 弹性盒
  • 网格
  • 花车
  • 定位
  • 表格布局
  • 多列布局

每种技术都有其用途、优点和缺点。没有任何技术被设计成可以单独使用。通过了解每种布局方法的设计目的,你将能够很好地了解哪种方法最适合每项任务。

¥Each technique has its uses, advantages, and disadvantages. No technique is designed to be used in isolation. By understanding what each layout method is designed for you'll be in a good position to understand which method is most appropriate for each task.

正常流量

¥Normal flow

正常流程是当你不执行任何控制页面布局时浏览器默认布局 HTML 页面的方式。让我们看一个简单的 HTML 示例:

¥Normal flow is how the browser lays out HTML pages by default when you do nothing to control page layout. Let's look at a quick HTML example:

html
<p>I love my cat.</p>

<ul>
  <li>Buy cat food</li>
  <li>Exercise</li>
  <li>Cheer up friend</li>
</ul>

<p>The end!</p>

默认情况下,浏览器会显示此代码,如下所示:

¥By default, the browser will display this code as follows:

请注意 HTML 如何按照其在源代码中出现的确切顺序显示,其中元素彼此堆叠 — 第一个段落,后面是无序列表,最后是第二个段落。

¥Note how the HTML is displayed in the exact order in which it appears in the source code, with elements stacked on top of one another — the first paragraph, followed by the unordered list, followed by the second paragraph.

一个在另一个之下出现的元素被描述为块元素,这与内联元素相反,内联元素像段落中的各个单词一样一个挨着一个出现。

¥The elements that appear one below the other are described as block elements, in contrast to inline elements, which appear beside one another like the individual words in a paragraph.

注意:块元素内容的布局方向被描述为块方向。块方向在英语等具有水平书写模式的语言中垂直运行。它可以在任何具有垂直书写模式的语言中水平运行,例如日语。相应的内联方向是内联内容(例如句子)运行的方向。

¥Note: The direction in which block element contents are laid out is described as the Block Direction. The Block Direction runs vertically in a language such as English, which has a horizontal writing mode. It would run horizontally in any language with a Vertical Writing Mode, such as Japanese. The corresponding Inline Direction is the direction in which inline contents (such as a sentence) would run.

对于页面上的许多元素,正常流程将准确创建你需要的布局。但是,对于更复杂的布局,你将需要使用 CSS 中可用的一些工具来更改此默认行为。从结构良好的 HTML 文档开始非常重要,因为这样你就可以使用默认的布局方式,而不是与之对抗。

¥For many of the elements on your page, the normal flow will create exactly the layout you need. However, for more complex layouts you will need to alter this default behavior using some of the tools available to you in CSS. Starting with a well-structured HTML document is very important because you can then work with the way things are laid out by default rather than fighting against it.

可以改变 CSS 中元素布局方式的方法有:

¥The methods that can change how elements are laid out in CSS are:

  • display 属性 - 标准值(例如 blockinlineinline-block)可以更改元素在正常流中的行为方式,例如,使块级元素的行为类似于内联级元素(有关详细信息,请参阅 CSS 盒子的类型)。我们还有通过特定 display 值启用的完整布局方法,例如 CSS 网格弹性盒,它们改变子元素在其父元素内部的布局方式。
  • 浮动 — 应用 float 值(例如 left)可能会导致块级元素沿着元素的一侧环绕,就像杂志布局中图片有时在其周围浮动文本的方式一样。
  • position 属性 — 允许你精确控制框在其他框内的放置。static 定位是正常流程中的默认设置,但你可以使用其他值使元素以不同方式布局,例如固定到浏览器视口的顶部。
  • 表格布局 - 为 HTML 表格的样式部分设计的功能可用于使用 display: table 和关联属性的非表格元素。
  • 多列布局 — 多列布局 属性可以使块的内容按列布局,就像你在报纸中看到的那样。

显示属性

¥The display property

CSS 中实现页面布局的主要方法都涉及指定 display 属性的值。此属性允许我们更改某些内容的默认显示方式。正常流程中的所有内容都有一个默认值 display;即元素设置行为的默认方式。例如,英语段落显示一个在另一个下面的事实是因为它们的样式为 display: block。如果你在段落内的某些文本周围创建链接,则该链接将与文本的其余部分保持内联,并且不会换行。这是因为 <a> 元素默认为 display: inline

¥The main methods for achieving page layout in CSS all involve specifying values for the display property. This property allows us to change the default way something displays. Everything in normal flow has a default value for display; i.e., a default way that elements are set to behave. For example, the fact that paragraphs in English display one below the other is because they are styled with display: block. If you create a link around some text inside a paragraph, that link remains inline with the rest of the text, and doesn't break onto a new line. This is because the <a> element is display: inline by default.

你可以更改此默认显示行为。例如,<li> 元素默认为 display: block,这意味着在我们的英文文档中,列表项显示在另一个之下。如果我们将显示值更改为 inline,它们将彼此相邻显示,就像句子中的单词一样。事实上,你可以更改任何元素的 display 值,这意味着你可以根据其语义来选择 HTML 元素,而无需关心它们的外观。它们的外观是你可以改变的。

¥You can change this default display behavior. For example, the <li> element is display: block by default, meaning that list items display one below the other in our English document. If we were to change the display value to inline they would display next to each other, as words would do in a sentence. The fact that you can change the value of display for any element means that you can pick HTML elements for their semantic meaning without being concerned about how they will look. The way they look is something that you can change.

除了能够通过将项目从 block 变为 inline(反之亦然)来更改默认呈现方式之外,还有一些更复杂的布局方法,它们以 display 的值开始。但是,在使用这些时,你通常需要调用其他属性。对于我们讨论布局来说最重要的两个值是 display: flexdisplay: grid

¥In addition to being able to change the default presentation by turning an item from block to inline and vice versa, there are some more involved layout methods that start out as a value of display. However, when using these you will generally need to invoke additional properties. The two values most important for our discussion of layout are display: flex and display: grid.

弹性盒

¥Flexbox

Flexbox 是 灵活的盒子布局 CSS 模块的简称,旨在让我们能够轻松地在一维上布局 - 无论是作为行还是作为列。要使用 Flexbox,请将 display: flex 应用于要布局的元素的父元素;然后它的所有直接子项都成为弹性项目。我们可以通过一个简单的例子看到这一点。

¥Flexbox is the short name for the Flexible Box Layout CSS module, designed to make it easy for us to lay things out in one dimension — either as a row or as a column. To use flexbox, you apply display: flex to the parent element of the elements you want to lay out; all its direct children then become flex items. We can see this in a simple example.

设置显示:flex

¥Setting display: flex

下面的 HTML 标记为我们提供了一个类为 wrapper 的包含元素,其中包含三个 <div> 元素。默认情况下,这些元素将显示为块元素,即在我们的英语文档中一个一个地显示。

¥The HTML markup below gives us a containing element with a class of wrapper, inside of which are three <div> elements. By default these would display as block elements, that is, below one another in our English language document.

但是,如果我们将 display: flex 添加到父级,则这三个项目现在会自行排列成列。这是因为它们成为弹性项目并受到弹性盒在弹性容器上设置的一些初始值的影响。它们显示在一行中是因为父元素的属性 flex-direction 的初始值为 row。它们看起来都在高度上拉伸,因为它们的父元素的属性 align-items 的初始值为 stretch。这意味着项目会拉伸到弹性容器的高度,在本例中是由最高的项目定义的。这些项目全部排列在容器的开头,在行的末尾留下任何额外的空间。

¥However, if we add display: flex to the parent, the three items now arrange themselves into columns. This is due to them becoming flex items and being affected by some initial values that flexbox sets on the flex container. They are displayed in a row because the property flex-direction of the parent element has an initial value of row. They all appear to stretch in height because the property align-items of their parent element has an initial value of stretch. This means that the items stretch to the height of the flex container, which in this case is defined by the tallest item. The items all line up at the start of the container, leaving any extra space at the end of the row.

css
* {
  box-sizing: border-box;
}
.wrapper > div {
  border-radius: 5px;
  background-color: rgb(207 232 220);
  padding: 1em;
}
css
.wrapper {
  display: flex;
}
html
<div class="wrapper">
  <div class="box1">One</div>
  <div class="box2">Two</div>
  <div class="box3">Three</div>
</div>

设置 flex 属性

¥Setting the flex property

除了可应用于 Flex 容器的属性外,还有可应用于 Flex 项目的属性。除其他外,这些属性可以改变物品弯曲的方式,使它们能够根据可用空间扩展或收缩。

¥In addition to properties that can be applied to a flex container, there are also properties that can be applied to flex items. These properties, among other things, can change the way that items flex, enabling them to expand or contract according to available space.

作为一个简单的示例,我们可以将 flex 属性添加到所有子项中,并为其指定值 1。这将导致所有项目增长并填满容器,而不是在末尾留下空间。如果空间更多,那么物品就会变得更宽;如果空间较少,它们就会变得更窄。此外,如果你向标记中添加另一个元素,其他项目都会变小以为其腾出空间;这些物品加在一起继续占据所有空间。

¥As a simple example, we can add the flex property to all of our child items, and give it a value of 1. This will cause all of the items to grow and fill the container, rather than leaving space at the end. If there is more space then the items will become wider; if there is less space they will become narrower. In addition, if you add another element to the markup, the other items will all become smaller to make space for it; the items all together continue taking up all the space.

css
* {
  box-sizing: border-box;
}
.wrapper > div {
  border-radius: 5px;
  background-color: rgb(207 232 220);
  padding: 1em;
}
css
.wrapper {
  display: flex;
}

.wrapper > div {
  flex: 1;
}
html
<div class="wrapper">
  <div class="box1">One</div>
  <div class="box2">Two</div>
  <div class="box3">Three</div>
</div>

注意:这是对 Flexbox 功能的非常简短的介绍。要了解更多信息,请参阅我们的 弹性盒 文章。

¥Note: This has been a very short introduction to what is possible in Flexbox. To find out more, see our Flexbox article.

网格布局

¥Grid Layout

Flexbox 是为一维布局设计的,而网格布局是为二维布局设计的 - 将内容按行和列排列。

¥While flexbox is designed for one-dimensional layout, Grid Layout is designed for two dimensions — lining things up in rows and columns.

设置显示:grid

¥Setting display: grid

与 Flexbox 类似,我们启用网格布局及其特定的显示值 — display: grid。下面的示例使用与 Flex 示例类似的标记,带有一个容器和一些子元素。除了使用 display: grid 之外,我们还分别使用 grid-template-rowsgrid-template-columns 属性为父级定义一些行和列轨道。我们定义了三列,每列 1fr,以及两行 100px。我们不需要对子元素设置任何规则;它们会自动放置到我们网格创建的单元格中。

¥Similar to flexbox, we enable Grid Layout with its specific display value — display: grid. The below example uses similar markup to the flex example, with a container and some child elements. In addition to using display: grid, we also define some row and column tracks for the parent using the grid-template-rows and grid-template-columns properties respectively. We've defined three columns, each of 1fr, as well as two rows of 100px. We don't need to put any rules on the child elements; they're automatically placed into the cells our grid's created.

css
* {
  box-sizing: border-box;
}

.wrapper > div {
  border-radius: 5px;
  background-color: rgb(207 232 220);
  padding: 1em;
}
css
.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 100px 100px;
  gap: 10px;
}
html
<div class="wrapper">
  <div class="box1">One</div>
  <div class="box2">Two</div>
  <div class="box3">Three</div>
  <div class="box4">Four</div>
  <div class="box5">Five</div>
  <div class="box6">Six</div>
</div>

将项目放置在网格上

¥Placing items on the grid

一旦有了网格,你就可以显式地将项目放置在其上,而不是依赖于上面看到的自动放置行为。在下面的下一个示例中,我们定义了相同的网格,但这次包含三个子项。我们使用 grid-columngrid-row 属性设置了每个项目的起始行和结束行。这会导致项目跨越多个轨道。

¥Once you have a grid, you can explicitly place your items on it, rather than relying on the auto-placement behavior seen above. In the next example below, we've defined the same grid, but this time with three child items. We've set the start and end line of each item using the grid-column and grid-row properties. This causes the items to span multiple tracks.

css
* {
  box-sizing: border-box;
}

.wrapper > div {
  border-radius: 5px;
  background-color: rgb(207 232 220);
  padding: 1em;
}
css
.wrapper {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 100px 100px;
  gap: 10px;
}

.box1 {
  grid-column: 2 / 4;
  grid-row: 1;
}

.box2 {
  grid-column: 1;
  grid-row: 1 / 3;
}

.box3 {
  grid-row: 2;
  grid-column: 3;
}
html
<div class="wrapper">
  <div class="box1">One</div>
  <div class="box2">Two</div>
  <div class="box3">Three</div>
</div>

注意:这两个例子只是展示了网格布局威力的一小部分。要了解更多信息,请参阅我们的 网格布局 文章。

¥Note: These two examples reveal just a small sample of the power of Grid layout. To learn more, see our Grid Layout article.

本指南的其余部分介绍了其他布局方法,这些方法对于页面的主布局不太重要,但仍然有助于实现特定任务。通过了解每个布局任务的性质,你很快就会发现,当你查看设计的特定组件时,最适合它的布局类型通常会很清楚。

¥The rest of this guide covers other layout methods that are less important for the main layout of your page, but still help to achieve specific tasks. By understanding the nature of each layout task you will soon find that when you look at a particular component of your design, the type of layout most suitable for it will often be clear.

花车

¥Floats

浮动元素会更改该元素以及正常流程中跟随该元素的块级元素的行为。浮动元素向左或向右移动并从正常流中移除,周围的内容浮动在其周围。

¥Floating an element changes the behavior of that element and the block level elements that follow it in normal flow. The floated element is moved to the left or right and removed from normal flow, and the surrounding content floats around it.

float 属性有四个可能的值:

¥The float property has four possible values:

  • left — 将元素向左浮动。
  • right — 将元素向右浮动。
  • none — 指定根本不浮动。这是默认值。
  • inherit — 指定 float 属性的值应从元素的父元素继承。

在下面的示例中,我们向左浮动 <div>,并在右侧赋予它 margin,以将周围的文本推离它。这为我们提供了文本包裹在盒装元素周围的效果,这是你需要了解的有关现代网页设计中使用的浮动的大部分内容。

¥In the example below, we float a <div> left and give it a margin on the right to push the surrounding text away from it. This gives us the effect of text wrapped around the boxed element, and is most of what you need to know about floats as used in modern web design.

css
body {
  width: 90%;
  max-width: 900px;
  margin: 0 auto;
}

p {
  line-height: 2;
  word-spacing: 0.1rem;
}

.box {
  background-color: rgb(207 232 220);
  border: 2px solid rgb(79 185 227);
  padding: 10px;
  border-radius: 5px;
}
html
<h1>Simple float example</h1>

<div class="box">Float</div>

<p>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam
  dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus
  ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus
  laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum,
  tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus
  neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat
  volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros
  pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec
  lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.
</p>
css
.box {
  float: left;
  width: 150px;
  height: 150px;
  margin-right: 30px;
}

注意:浮点数在我们关于 浮动并清除 属性的课程中得到了充分的解释。在 Flexbox 和网格布局等技术出现之前,浮动被用作创建列布局的方法。你可能仍然会在网络上遇到这些方法;我们将在 遗留布局方法 课程中介绍这些内容。

¥Note: Floats are fully explained in our lesson on the float and clear properties. Prior to techniques such as Flexbox and Grid Layout, floats were used as a method of creating column layouts. You may still come across these methods on the web; we will cover these in the lesson on legacy layout methods.

定位技巧

¥Positioning techniques

定位允许你将元素从正常流中放置的位置移动到另一个位置。定位不是创建页面主要布局的方法;而是创建页面主布局的方法。它更多的是关于管理和微调页面上特定项目的位置。

¥Positioning allows you to move an element from where it would otherwise be placed in normal flow over to another location. Positioning isn't a method for creating the main layouts of a page; it's more about managing and fine-tuning the position of specific items on a page.

然而,有一些有用的技术可以获取依赖于 position 属性的特定布局模式。了解定位还有助于理解正常流程,以及将项目移出正常流程意味着什么。

¥There are, however, useful techniques for obtaining specific layout patterns that rely on the position property. Understanding positioning also helps in understanding normal flow, and what it means to move an item out of the normal flow.

你应该了解五种定位类型:

¥There are five types of positioning you should know about:

  • 静态定位是每个元素的默认定位。它只是意味着 "将元素置于文档布局流中的正常位置 - 这里没有什么特别可看的"。
  • 相对定位允许你修改元素在页面上的位置,将其相对于正常流中的位置移动,以及使其与页面上的其他元素重叠。
  • 绝对定位将元素完全移出页面的正常布局流,就像它位于自己的单独层上一样。从那里,你可以将其固定到相对于其最近定位的祖级的边缘的位置(如果没有定位其他祖级,则该位置将变为 <html>)。这对于创建复杂的布局效果非常有用,例如选项卡式框,其中不同的内容面板相互叠置并根据需要显示和隐藏,或者信息面板默认位于屏幕外,但可以在屏幕上滑动 使用控制按钮。
  • 固定定位与绝对定位非常相似,只不过它相对于浏览器视口固定一个元素,而不是另一个元素。这对于创建效果非常有用,例如当其余内容滚动时始终保持在屏幕上的同一位置的持久导航菜单。
  • 粘性定位是一种较新的定位方法,它使元素的行为类似于 position: relative,直到它达到距视口的定义偏移量,此时它的行为类似于 position: fixed

简单定位示例

¥Simple positioning example

为了让你熟悉这些页面布局技术,我们将向你展示几个快速示例。我们的示例都将具有相同的 HTML 结构(标题后跟三个段落),如下所示:

¥To provide familiarity with these page layout techniques, we'll show you a couple of quick examples. Our examples will all feature the same HTML structure (a heading followed by three paragraphs), which is as follows:

html
<h1>Positioning</h1>

<p>I am a basic block level element.</p>
<p class="positioned">I am a basic block level element.</p>
<p>I am a basic block level element.</p>

默认情况下,该 HTML 将使用以下 CSS 进行样式设置:

¥This HTML will be styled by default using the following CSS:

css
body {
  width: 500px;
  margin: 0 auto;
}

p {
  background-color: rgb(207 232 220);
  border: 2px solid rgb(79 185 227);
  padding: 10px;
  margin: 10px;
  border-radius: 5px;
}

.positioned {
  background: rgb(255 84 104 / 30%);
  border: 2px solid rgb(255 84 104);
}

渲染输出如下:

¥The rendered output is as follows:

相对定位

¥Relative positioning

相对定位允许你将项目从正常流程中的默认位置偏移。这意味着你可以完成一项任务,例如将图标向下移动一点,使其与文本标签对齐。为此,我们可以添加以下规则来添加相对定位:

¥Relative positioning allows you to offset an item from its default position in normal flow. This means you could achieve a task such as moving an icon down a bit so it lines up with a text label. To do this, we could add the following rule to add relative positioning:

css
.positioned {
  position: relative;
  top: 30px;
  left: 30px;
}

这里我们将中间段落的 position 值设置为 relative。它本身不会执行任何操作,因此我们还添加 topleft 属性。这些用于将受影响的元素向下和向右移动。这可能看起来与你的预期相反,但你需要将其视为元素被推到其左侧和顶部,这会导致它向右和向下移动。

¥Here we give our middle paragraph a position value of relative. This doesn't do anything on its own, so we also add top and left properties. These serve to move the affected element down and to the right. This might seem like the opposite of what you were expecting, but you need to think of it as the element being pushed on its left and top sides, which results in it moving right and down.

添加此代码将得到以下结果:

¥Adding this code will give the following result:

html
<h1>Relative positioning</h1>

<p>I am a basic block level element.</p>
<p class="positioned">This is my relatively positioned element.</p>
<p>I am a basic block level element.</p>
css
body {
  width: 500px;
  margin: 0 auto;
}

p {
  background-color: rgb(207 232 220);
  border: 2px solid rgb(79 185 227);
  padding: 10px;
  margin: 10px;
  border-radius: 5px;
}

.positioned {
  background: rgb(255 84 104 / 30%);
  border: 2px solid rgb(255 84 104);
}

绝对定位

¥Absolute positioning

绝对定位用于从正常流中完全删除元素,并使用距包含块边缘的偏移量来定位它。

¥Absolute positioning is used to completely remove an element from the normal flow and instead position it using offsets from the edges of a containing block.

回到我们最初的非定位示例,我们可以添加以下 CSS 规则来实现绝对定位:

¥Going back to our original non-positioned example, we could add the following CSS rule to implement absolute positioning:

css
.positioned {
  position: absolute;
  top: 30px;
  left: 30px;
}

在这里,我们为中间段落指定了 positionabsolute 以及与之前相同的 topleft 属性。添加此代码将产生以下结果:

¥Here we give our middle paragraph a position value of absolute and the same top and left properties as before. Adding this code will produce the following result:

html
<h1>Absolute positioning</h1>

<p>I am a basic block level element.</p>
<p class="positioned">This is my absolutely positioned element.</p>
<p>I am a basic block level element.</p>
css
body {
  width: 500px;
  margin: 0 auto;
}

p {
  background-color: rgb(207 232 220);
  border: 2px solid rgb(79 185 227);
  padding: 10px;
  margin: 10px;
  border-radius: 5px;
}

.positioned {
  background: rgb(255 84 104 / 30%);
  border: 2px solid rgb(255 84 104);
}

这是非常不同的!定位元素现在已与页面布局的其余部分完全分离,并位于其顶部。其他两个段落现在坐在一起,就好像它们的定位兄弟不存在一样。topleft 属性对绝对定位元素的影响与对相对定位元素的影响不同。在本例中,偏移量是从页面顶部和左侧计算的。可以更改成为此容器的父元素,我们将在 positioning 的课程中了解这一点。

¥This is very different! The positioned element has now been completely separated from the rest of the page layout and sits over the top of it. The other two paragraphs now sit together as if their positioned sibling doesn't exist. The top and left properties have a different effect on absolutely positioned elements than they do on relatively positioned elements. In this case, the offsets have been calculated from the top and left of the page. It is possible to change the parent element that becomes this container and we will take a look at that in the lesson on positioning.

固定定位

¥Fixed positioning

固定定位以与绝对定位相同的方式从文档流中删除我们的元素。但是,它们不是从容器应用偏移,而是从视口应用。由于该项目相对于视口保持固定,因此我们可以创建效果,例如当页面在其下方滚动时保持固定的菜单。

¥Fixed positioning removes our element from document flow in the same way as absolute positioning. However, instead of the offsets being applied from the container, they are applied from the viewport. Because the item remains fixed in relation to the viewport, we can create effects such as a menu that remains fixed as the page scrolls beneath it.

对于这个例子,我们的 HTML 包含三段文本,以便我们可以滚动页面,以及一个属性为 position: fixed 的框。

¥For this example, our HTML contains three paragraphs of text so that we can scroll through the page, as well as a box with the property of position: fixed.

html
<h1>Fixed positioning</h1>

<div class="positioned">Fixed</div>

<p>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam
  dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus
  ut, rutrum luctus orci.
</p>

<p>
  Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed
  auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci
  vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex
  malesuada et.
</p>

<p>
  In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet
  turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas
  augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id
  ornare felis, eget fermentum sapien.
</p>
css
body {
  width: 500px;
  margin: 0 auto;
}

.positioned {
  background: rgb(255 84 104 / 30%);
  border: 2px solid rgb(255 84 104);
  padding: 10px;
  margin: 10px;
  border-radius: 5px;
}
css
.positioned {
  position: fixed;
  top: 30px;
  left: 30px;
}

粘性定位

¥Sticky positioning

粘性定位是我们可以使用的最终定位方法。它将相对定位与固定定位混合在一起。当项目具有 position: sticky 时,它将按正常流程滚动,直到达到我们定义的视口的偏移量。此时,它会变成 "stuck",就像应用了 position: fixed 一样。

¥Sticky positioning is the final positioning method that we have at our disposal. It mixes relative positioning with fixed positioning. When an item has position: sticky, it'll scroll in normal flow until it hits offsets from the viewport that we have defined. At that point, it becomes "stuck" as if it had position: fixed applied.

html
<h1>Sticky positioning</h1>

<p>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam
  dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus
  ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus
  laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum,
  tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus
  neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat
  volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros
  pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec
  lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.
</p>

<div class="positioned">Sticky</div>

<p>
  Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada
  ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed
  est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus
  tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus
  sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis
  vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque
  penatibus et magnis dis parturient montes, nascetur ridiculus mus.
</p>

<p>
  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam
  dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus
  ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus
  laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum,
  tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus
  neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat
  volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros
  pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec
  lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.
</p>
css
body {
  width: 500px;
  margin: 0 auto;
}

.positioned {
  background: rgb(255 84 104 / 30%);
  border: 2px solid rgb(255 84 104);
  padding: 10px;
  margin: 10px;
  border-radius: 5px;
}
css
.positioned {
  position: sticky;
  top: 30px;
  left: 30px;
}

注意:要了解有关定位的更多信息,请参阅我们的 定位 文章。

¥Note: To find out more about positioning, see our Positioning article.

表格布局

¥Table layout

HTML 表格非常适合显示表格数据,但很多年前,甚至在跨浏览器可靠地支持基本 CSS 之前,Web 开发者也曾经使用表格来进行整个网页布局,将页眉、页脚、列等放入各种表格中 行和列。这在当时是可行的,但是存在很多问题:表格布局不灵活,标记非常繁重,难以调试,并且语义错误(例如,屏幕阅读器用户在导航表格布局时遇到问题)。

¥HTML tables are fine for displaying tabular data, but many years ago — before even basic CSS was supported reliably across browsers — web developers used to also use tables for entire web page layouts, putting their headers, footers, columns, etc. into various table rows and columns. This worked at the time, but it has many problems: table layouts are inflexible, very heavy on markup, difficult to debug, and semantically wrong (e.g., screen reader users have problems navigating table layouts).

使用表格标记时表格在网页上的外观取决于一组定义表格布局的 CSS 属性。这些相同的属性也可用于布局非表格元素,这种用途有时被描述为 "使用 CSS 表格"。

¥The way that a table looks on a webpage when you use table markup is due to a set of CSS properties that define table layout. These same properties can also be used to lay out elements that aren't tables, a use which is sometimes described as "using CSS tables".

下面的例子展示了一种这样的用法。必须注意的是,使用 CSS 表进行布局此时应被视为遗留方法,并且仅应用于支持缺乏 Flexbox 或 Grid 支持的旧浏览器。

¥The example below shows one such use. It must be noted, that using CSS tables for layout should be considered a legacy method at this point, and should only be used to support old browsers that lack support for Flexbox or Grid.

让我们看一个例子。首先,一些创建 HTML 表单的简单标记。每个输入元素都有一个标签,我们还在段落中添加了标题。为了布局目的,每个标签/输入对都封装在 <div> 中。

¥Let's look at an example. First, some simple markup that creates an HTML form. Each input element has a label, and we've also included a caption inside a paragraph. Each label/input pair is wrapped in a <div> for layout purposes.

html
<form>
  <p>First of all, tell us your name and age.</p>
  <div>
    <label for="fname">First name:</label>
    <input type="text" id="fname" />
  </div>
  <div>
    <label for="lname">Last name:</label>
    <input type="text" id="lname" />
  </div>
  <div>
    <label for="age">Age:</label>
    <input type="text" id="age" />
  </div>
</form>

至于 CSS,除了 display 属性的使用之外,大部分都相当普通。<form><div><label><input> 被告知分别显示为表格、表格行和表格单元格。基本上,它们的行为就像 HTML 表格标记,导致标签和输入默认情况下很好地对齐。然后我们要做的就是添加一些尺寸、边距等,让一切看起来更好一点,我们就完成了。

¥As for the CSS, most of it's fairly ordinary except for the uses of the display property. The <form>, <div>s, and <label>s and <input>s have been told to display like a table, table rows, and table cells respectively. Basically, they'll act like HTML table markup, causing the labels and inputs to line up nicely by default. All we then have to do is add a bit of sizing, margin, etc., to make everything look a bit nicer and we're done.

你会注意到,标题段落已被赋予 display: table-caption;,这使得它的行为类似于表格 <caption>,而 caption-side: bottom; 则告诉标题位于表格底部以用于样式目的,即使标记位于 <input> 元素之前 来源。这提供了一定的灵活性。

¥You'll notice that the caption paragraph has been given display: table-caption;, which makes it act like a table <caption>, and caption-side: bottom; to tell the caption to sit on the bottom of the table for styling purposes, even though the markup is before the <input> elements in the source. This allows for a nice bit of flexibility.

css
html {
  font-family: sans-serif;
}

form {
  display: table;
  margin: 0 auto;
}

form div {
  display: table-row;
}

form label,
form input {
  display: table-cell;
  margin-bottom: 10px;
}

form label {
  width: 200px;
  padding-right: 5%;
  text-align: right;
}

form input {
  width: 300px;
}

form p {
  display: table-caption;
  caption-side: bottom;
  width: 300px;
  color: #999;
  font-style: italic;
}

这给了我们以下结果:

¥This gives us the following result:

你还可以在 css-tables-example.html 现场观看此示例(也可以在 源代码 观看。)

¥You can also see this example live at css-tables-example.html (see the source code too.)

注意:与本页的其他主题不同,表布局由于其遗留应用而不会在本模块中进一步介绍。

¥Note: Table layout, unlike the other topics of this page, won't be further covered in this module due to its legacy application.

多列布局

¥Multi-column layout

多列布局 CSS 模块为我们提供了一种按列布局内容的方法,类似于文本在报纸中的流动方式。虽然由于用户必须上下滚动,所以在网络环境中向上和向下阅读列不太有用,但将内容排列到列中仍然是一种有用的技术。

¥The multi-column layout CSS module provides us a way to lay out content in columns, similar to how text flows in a newspaper. While reading up and down columns is less useful in a web context due to the users having to scroll up and down, arranging content into columns can, nevertheless, be a useful technique.

要将块变成多列容器,我们使用 column-count 属性(它告诉浏览器我们想要有多少列)或 column-width 属性(它告诉浏览器用尽可能多的列填充容器) 具有指定的宽度。

¥To turn a block into a multi-column container, we use either the column-count property, which tells the browser how many columns we would like to have, or the column-width property, which tells the browser to fill the container with as many columns as possible of a specified width.

在下面的示例中,我们从包含类 container<div> 元素内的 HTML 块开始。

¥In the below example, we start with a block of HTML inside a containing <div> element with a class of container.

html
<div class="container">
  <h1>Multi-column Layout</h1>

  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus
    aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci,
    pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at
    ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta.
  </p>

  <p>
    Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada
    ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed
    est. Nam id risus quis ante semper consectetur eget aliquam lorem.
  </p>

  <p>
    Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris
    ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus
    viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum
    sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
    mus.
  </p>
</div>

我们在该容器上使用 200 像素的 column-width,导致浏览器创建尽可能多的 200 像素列。列之间剩余的任何空间都将被共享。

¥We're using a column-width of 200 pixels on that container, causing the browser to create as many 200 pixel columns as will fit. Whatever space is left between the columns will be shared.

css
body {
  max-width: 800px;
  margin: 0 auto;
}
css
.container {
  column-width: 200px;
}

概括

¥Summary

本文简要总结了你应该了解的所有布局技术。请继续阅读,了解有关每种技术的更多信息!

¥This article has provided a brief summary of all the layout technologies you should know about. Read on for more information on each individual technology!