布局

CSS 播客 - 009:布局

假设您是一名开发者 一位设计师同事为你提供一个全新网站的设计方案 设计包含各种有趣的布局和构图: 考虑视口宽度和高度的二维布局, 以及需要流畅、灵活的布局 如何使用 CSS 确定样式的最佳方式?

CSS 为我们提供了多种方法来解决布局问题 或同时设置纵轴和/或横轴 为上下文选择正确的布局方法可能很困难, 通常,您可能需要多种布局方法来解决问题。 为帮助理解这一点,在以下单元中 您将了解每种 CSS 布局机制的独特功能,以便做出明智的决策。

布局:简史

在网络发展的早期阶段 比简单文档更复杂一些的设计则使用 <table> 元素进行布局。 20 世纪 90 年代末,当 CSS 被浏览器广泛采用后,让 HTML 与视觉样式的分离变得更加简单。 CSS 让开发者无需更改 HTML 即可完全改变网站的外观和风格。 这一新功能为 CSS Zen Garden 等项目提供了灵感, 它展示了 CSS 的强大功能,可以鼓励更多开发者学习。

随着我们对网页设计和浏览器技术需求的演变,CSS 也在不断发展。 您可以了解到 CSS 布局是如何发展的,以及我们布局方法的演变过程 作者:Rachel Andrew

显示 CSS 从 1996 年到 2021 年这些年来演变的时间轴

布局:现在和未来

现代 CSS 具有极其强大的布局工具。 我们有专门的布局系统,接下来我们将大致了解可供我们使用的内容, 我们会在下一单元中详细介绍 Flexbox 和 Grid。

了解 display 属性

display 属性会执行两项操作。 它首先会确定应用此框的框是作为 inline 还是 block。

.my-element {
  display: inline;
}

内嵌元素的行为类似于句子中的字词。 它们按内嵌方向并排排列。 <span><strong> 等元素, 通常用于为包含元素(例如 <p>、段落)中的文本设置样式, 都采用内联形式 它们还会保留周围的空白。

一张示意图,显示了所有不同大小的盒子以及每个大小调整部分的开始和结束

您无法为内嵌元素设置明确的宽度和高度。 周围的元素将忽略任何块级外边距和内边距。

.my-element {
    display: block;
}

Block 元素不并排放置。 为自己创造了新的界限。除非被其他 CSS 代码更改 一个 block 元素会展开为 inline 尺寸, 因此在水平书写模式下跨越整个宽度。 将遵循块元素四周的外边距。

.my-element {
    display: flex;
}

display 属性还可确定元素的子项的行为方式。 例如: 将 display 属性设置为 display: flex 会使 Box 成为块级框, 并将其子项转换为 flex 项。 这将启用用于控制对齐、排序和流畅的 flex 属性。

Flexbox 和网格

有两种主要的布局机制可以为多个元素创建布局规则:flexboxgrid。 它们有相似之处,但旨在解决不同的布局问题。

Flexbox

.my-element {
    display: flex;
}

Flexbox 是一种一维布局的布局机制。 沿单轴布局(水平或垂直)。 默认情况下,Flexbox 会并排对齐元素的子元素, 在内联方向上 沿砌块方向拉伸,使其高度相同。

项在空间用尽后将保持在同一轴上且不换行。 相反,它们会尝试彼此挤压到同一行。 您可以使用 align-itemsjustify-contentflex-wrap 属性更改此行为。

Flexbox 还会将子元素转换为 flex 项, 这意味着您可以编写规则,指定它们在 Flex 容器内的行为方式。 您可以更改单个项的对齐方式、顺序和对齐方式。 您还可以使用 flex 属性更改缩放方式。

.my-element div {
    flex: 1 0 auto;
}

flex 属性是 flex-growflex-shrinkflex-basis 的简写形式。 您可以按如下方式展开上面的示例:

.my-element div {
 flex-grow: 1;
 flex-shrink: 0;
 flex-basis: auto;
}

开发者提供这些低级规则,以提示浏览器布局的行为方式 当内容和视口尺寸有挑战时。 这使其成为一种非常实用的响应式网页设计机制。

网格

.my-element {
    display: grid;
}

网格在很多方面与 flexbox 相似, 但它旨在控制多轴布局,而不是单轴布局(垂直或水平空间)。

借助网格,您可以在具有 display: grid 的元素上编写布局规则, 并引入了一些用于布局样式的新基元, 例如 repeat()minmax() 函数。 fr 单元是剩余空间的一部分,这是一种非常实用的网格单元。您可以构建传统的 12 列网格, 并在每一项之间留出间隙,使用 3 个 CSS 属性:

.my-element {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 1rem;
}

上面的示例展示了单轴布局。 Flexbox 大多将列表项视为一个组, 网格,可让您精确控制其在两个维度中的位置。 我们可以定义此网格中的第一项占据 2 行 3 列:

.my-element :first-child {
  grid-row: 1/3;
  grid-column: 1/4;
}

grid-rowgrid-column 属性用于指示网格中的第一个元素跨越到第四列的开头, 从第一列开始,然后跨越到第三行(即从第一行开始)。

流布局

如果不使用网格或 Flexbox 您的元素会以正常流程显示。 有许多布局方法可用于调整项在正常流动时的行为和位置。

内嵌块

还记得吗,周围元素是如何不遵循内嵌元素的块外边距和内边距的? 使用 inline-block,您可以导致这种情况。

p span {
    display: inline-block;
}

使用 inline-block 会得到一个具有块级元素某些特征的框, 但仍与文字浑然一体

p span {
    margin-top: 0.5rem;
}

浮点数

如果您有一张图片包含在一段文字中, 用文字环绕在图片周围,就像在报纸中看到的那样,是不是很方便? 您可以使用浮点数做到这一点。

img {
    float: left;
    margin-right: 1em;
}

float 属性指示元素“浮动”向指定方向行驶 此示例中的图片指示其向左浮动, 然后允许同级元素“封装”。 您可以指示元素浮动 leftrightinherit

多列布局

如果您的元素列表非常长 例如,列出世界上所有国家/地区 否则可能会为用户带来大量的滚动浏览和时间。 它还会在网页上产生多余的空白。 借助 CSS 多列功能 您可以将其拆分为多个列,以帮助解决这两个问题。

<h1>All countries</h1>
<ul class="countries">
  <li>Argentina</li>
  <li>Aland Islands</li>
  <li>Albania</li>
  <li>Algeria</li>
  <li>American Samoa</li>
  <li>Andorra</li>
  …
</ul>
.countries {
    column-count: 2;
    column-gap: 1em;
}

这会自动将这个长列表拆分为两列,并在两列之间添加间隙。

.countries {
    width: 100%;
    column-width: 260px;
    column-gap: 1em;
}

您不必设置将内容拆分到多少列, 您还可以使用 column-width 定义所需的最小宽度。 随着视口中的可用空间越来越多 随着空间的减少,系统会自动创建更多列 列也会减少。 这在响应式网页设计环境中非常有用。

定位

下面我们要简单介绍一下布局机制,即定位。 position 属性可更改元素在文档正常流程中的行为方式, 以及它与其他元素之间的关系 可用选项包括 relativeabsolutefixedsticky,默认值为 static

.my-element {
  position: relative;
  top: 10px;
}

根据该元素在文档中的当前位置,将它下移 10 像素。 与自身为相对位置 向元素添加 position: relative 也会使其成为具有 position: absolute 的所有子元素的包含块。 这意味着其子项现在将被重新放置到这个特定元素上, 而不是最顶层的相对父项,则它会应用绝对位置。

.my-element {
  position: relative;
  width: 100px;
  height: 100px;
}

.another-element {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 50px;
    height: 50px;
}

position 设置为 absolute 时, 它会将相应元素从当前文档流中分离开来 这意味着有两点:

  1. 您可以使用 toprightbottomleft 在其最接近的相对父项中随意定位此元素。
  2. 绝对元素周围的所有内容都会重排以填充该元素剩余的剩余空间。

position 值为 fixed 的元素的行为方式与 absolute 类似, 其父项是根 <html> 元素。 固定位置元素会根据您设置的 toprightbottomleft 值从左上角锚定。

您可以实现锚定、 通过使用 sticky,修复了 fixed 的方面以及 relative 中可预测的文档流程执行方面的更加可预测性。 使用此值时,当视口滚动越过该元素时, 它会固定在您设置的 toprightbottomleft 值上。

小结

CSS 布局具有丰富的选择和灵活性。 要深入了解 CSS FlexboxGrid 的强大功能,请继续学习接下来的几个单元。

检查您的理解情况

测试您对布局知识的掌握情况

display 属性有哪两项作用?

确定 inlineblocknone
布局引擎需要知道此框是否为全宽,以及是否需要换行。
确定网格布局帧。
display 属性可以将 display 设置为 grid,但与布局框架无关。
确定子元素的行为方式。
Flexbox 和网格可为孩子提供观点和新功能。
确定是否应滚动该框。
也就是 overflow 属性。

将多个段落拆分成多个列,哪个 CSS 属性最适合 任务?

display: grid
虽然网格可以将多个段落放入多个列中,但这些列将是各自的列,而不是从一个列指向下一个列。
column-count
段落将从一列的末尾移动到下一列的开头,就像杂志或报纸一样。
display: flex
虽然 flex 可以将多个段落放入列中,但这些列将是自己的列,不需要像以前一样从一个列流向下一个列。
float
再试一次!

如果某个块不在流程下方,这意味着什么?

它卡在河边了。
这里的上下文是 CSS,而不是地理位置。
已指定 topleft 位置值。
仅具有这些属性并不会使流程脱离流程。
系统不再根据同级元素的位置来确定合适的位置。
例如,具有 position: absolute 的框现在的位置是 x 和 y 坐标(基于包含块,而不是其与其他同级元素的顺序)确定的。

Flexbox 和 Grid 是否默认封装其子项?

正确
必须通过 flex-wrap: wraprepeat(auto-fit, 30ch) 选择启用。
错误
Flexbox 和网格具有特殊的环绕功能,需要其他样式才能应用。