如何在 CSS 中对齐事物
已发表: 2022-03-10今天,我们有很多方法可以在 CSS 中对齐事物,但使用哪种方法并不总是一个显而易见的决定。 然而,知道什么是可用的意味着如果你遇到一个特定的对齐问题,你总是可以尝试一些策略。
在本文中,我将介绍不同的对齐方法。 我不会为每个人提供全面的指南,而是解释人们的一些症结,并指出更完整的属性和值参考。 与大多数 CSS 一样,您可以通过了解有关方法行为方式的基本知识来走很长的路,然后需要一个地方去查找有关如何实现所需精确布局的更精细的细节。
对齐文本和内联元素
当我们在页面上有一些文本和其他内联元素时,每一行内容都被视为一个行框。 属性text-align
将对齐页面上的内容,例如,如果您希望文本居中或对齐。 但是,有时您可能希望将该行框中的内容与其他内容对齐,例如,如果您有一个图标显示在文本旁边,或者不同大小的文本。
在下面的示例中,我有一些带有较大内联图像的文本。 我在图像上使用vertical-align: middle
将文本与图像的中间对齐。
line-height
属性和对齐方式
记住line-height
属性会改变 line-box 的大小,因此可以改变你的对齐方式。 以下示例使用 150px 的大 line-height 值,并且我已将图像对齐到top
。 图像与行框的顶部对齐,而不是文本的顶部,删除该行高或使其小于图像的大小,图像和文本将在文本的顶部对齐。
事实证明, line-height
和文本的大小确实相当复杂,我不打算在本文中深入探讨这个兔子洞。 如果您尝试精确对齐内联元素并想真正了解发生了什么,我建议您阅读“Deep Dive CSS: Font Metrics, line-height
and vertical-align
”。
什么时候可以使用vertical-align
属性?
如果要对齐任何内联元素, vertical-align
属性很有用。 这包括带有display: inline-block
元素。 表格单元格的内容也可以使用vertical-align
属性对齐。
vertical-align
属性对弹性或网格项目没有影响,因此如果用作后备策略的一部分,它将在父元素变成网格或弹性容器的那一刻停止应用。 例如,在下一支笔中,我有一组用display: inline-block
布局的项目,这意味着即使浏览器没有 Flexbox,我也可以对齐项目:
在下一篇文章中,我将inline-block
视为 Flex 布局的后备。 对齐属性不再适用,我可以添加align-items
来对齐 Flexbox 中的项目。 您可以看出 Flexbox 方法正在发挥作用,因为使用display: inline-block
时您将获得的项目之间的间隙消失了。
vertical-align
在表格单元格上起作用的事实是使用display: table-cell
使项目垂直居中的技巧起作用的原因。
现在我们确实有更好的方法来对齐 CSS 中的框(我们将在下一节中看到),我们不需要在除了 inline 和 text 元素之外的地方使用vertical-align
和text-align
属性他们被设计的。 但是,它们在这些文本和内联格式中使用仍然完全有效,因此请记住,如果您尝试内联对齐某些内容,则需要使用这些属性而不是 Box Alignment 属性。
框对齐
Box Alignment Specification 处理我们如何对齐其他所有内容。 该规范详细说明了以下对齐属性:
-
justify-content
-
align-content
-
justify-self
-
align-self
-
justify-items
-
align-items
您可能已经将这些属性视为 Flexbox 规范或 Grid 的一部分。 属性的历史是它们起源于 Flexbox 的一部分,并且仍然存在于 Level 1 规范中; 然而,当它们变得更普遍有用时,它们被转移到自己的规范中。 我们现在也在网格布局中使用它们,并且它们也被指定用于其他布局方法,尽管当前的浏览器支持意味着你还不能使用它们。
因此,下次互联网上有人告诉你垂直对齐是 CSS 中最难的部分时,你可以告诉他们(这甚至适合推文):
.container { display: flex; align-items: center; justify-content: center; }
将来,一旦为块布局实现了 Box Alignment 属性,我们甚至可以省去display: flex
。 然而,目前,让你想要的东西的父对象居中一个 flex 容器是水平和垂直对齐的方法。
两种对齐方式
对齐 flex 和 grid 项目时,您有两种可能的对齐方式:
- 您在网格或弹性容器中有空闲空间(一旦项目或轨道布置好)。
- 您还可以将项目本身放在放置它的网格区域内,或者在 flex 容器内的交叉轴上。
我在上面展示了一组属性,对齐属性可以被认为是两组。 处理空闲空间分配的那些,以及对齐项目本身的那些。
处理备用空间: align-content
和justify-content
以-content
结尾的属性是关于空间分配的,因此当您选择使用align-content
或justify-content
时,您是在网格轨道或弹性项目之间分配可用空间。 它们本身不会改变 flex 或 grid 项目的大小; 他们移动它们是因为它们改变了空闲空间的去向。
下面,我有一个 flex 示例和一个 grid 示例。 两者都有一个大于显示弹性项目或网格轨道所需的容器,因此我可以使用align-content
和justify-content
来分配该空间。
移动项目: justify-self
, align-self
, justify-items
和align-items
然后我们align-self
和justify-self
应用于单个 flex 或 grid 项目; 您还可以在容器上使用align-items
和justify-items
来一次设置所有属性。 这些属性处理实际的弹性或网格项目,即在网格区域或弹性线内移动内容。
- 网格布局
您可以获得这两个属性,因为您可以在块和内联轴上移动项目,因为我们定义了它所在的网格区域。 - 弹性布局
您只能在交叉轴上对齐,因为主轴仅由空间分布控制。 因此,如果您的项目是一排,您可以使用align-self
在 flex line 内上下移动它们,使它们相互对齐。
在下面的示例中,我有一个 flex 和一个网格容器,并在 Flexbox 中使用align-items
和align-self
来在交叉轴上上下移动项目。 如果您使用 Firefox,并使用 Firefox Flexbox Inspector 检查元素,您可以看到 flex 容器的大小以及项目如何在其中垂直移动。
在网格中,我可以使用所有四个属性在网格区域内移动项目。 再一次,Firefox DevTools Grid Inspector 在玩对齐时会很有用。 叠加网格线后,您可以看到内容正在移动的区域:
使用 CodePen 演示中的值来查看如何在每种布局方法中移动内容:
被align
和justify
弄糊涂了
人们在 Grid 和 Flexbox 中记住对齐属性时被引用的问题之一是,没有人能记住是对齐还是对齐。 哪个方向是哪个?
对于网格布局,您需要知道您是在块方向还是内联方向上对齐。 块方向是在您的页面上布置的方向块(在您的写作模式下),即垂直的英语。 内联方向是句子运行的方向(因此对于水平从左到右的英语)。
要在块方向上对齐事物,您将使用以align-
开头的属性。 如果网格容器中有空闲空间,您可以使用align-content
在网格轨道之间分配空间,并使用align-items
或align-self
在已放置的网格区域内移动项目。
下面的示例有两个网格布局。 一个有writing-mode: horizontal-tb
(这是英语的默认设置)和另一个writing-mode: vertical-rl
。 这是他们之间唯一的区别。 您可以看到我应用的对齐属性在两种模式下在块轴上的工作方式完全相同。
要将事物沿内联方向对齐,请使用以justify-
开头的属性。 使用justify-content
在网格轨道之间分配空间,并使用justify-items
或justify-self
以沿内联方向对齐网格区域内的项目。
再一次,我有两个网格布局示例,因此您可以看到内联始终是内联的——无论您使用哪种书写模式。
Flexbox 有点棘手,因为我们有一个可以更改为row
或column
的主轴。 所以,让我们首先考虑一下主轴。 它使用flex-direction
属性设置。 此属性的初始(或默认)值是row
,它将在当前使用的书写模式下将 flex 项目排列为一行 - 这就是为什么在使用英语工作时,当我们创建一个弹性容器。 然后,您可以将主轴更改为flex-direction: column
并且项目将被布置为列,这意味着它们在该书写模式下以块方向布置。
由于我们可以进行轴切换,Flexbox 中最重要的因素是询问“哪个轴是我的主轴?” 一旦你知道了,那么为了对齐(在你的主轴上)你只需使用justify-content
。 您的主轴是行还是列都没有关系。 您可以使用justify-content
控制弹性项目之间的空间。
在交叉轴上,您可以使用align-items
对齐弹性容器内的项目或多行弹性容器中的弹性线。 如果你有一个使用flex-wrap: wrap
的多行容器并且在该容器中有空间,你可以使用align-content
在交叉轴上分配空间。
在下面的示例中,我们同时使用显示为行和列的 flex 容器:
当justify-content
或align-content
不起作用时
Grid 和 Flexbox 中的justify-content
和align-content
属性是关于分配额外空间的。 所以要检查的是你有额外的空间。
这是一个 Flex 示例:我设置了flex-direction: row
并且我有三个项目。 它们不会占用 flex 容器中的所有空间,所以我在主轴上有空闲空间, justify-content
的初始值是flex-start
,所以我的项目都在开始时排成一行,额外的空间是在最后。 我正在使用 Firefox Flex Inspector 突出显示空间。
如果我将 flex-direction 更改为space-between
,那么现在将在项目之间分配额外的空间:
如果我现在向我的项目添加更多内容,使它们变得更大并且不再有任何额外的空间,那么justify-content
什么也不做——只是因为没有空间可以分发。
我被问到的一个常见问题是为什么当flex-direction
为column
时justify-content
不起作用。 这一般是因为没有空间可以分发。 如果您采用上面的示例并将其设为flex-direction: column
,则项目将显示为一列,但项目下方不会像您执行flex-direction: row
时那样有额外的空间。 这是因为当你使用display: flex
创建一个 Flex 容器时,你有一个块级的 flex 容器; 这将占用内联方向上的所有可能空间。 在 CSS 中,事物不会在块方向上拉伸,因此没有多余的空间。
为容器添加一个高度——只要它超过显示项目所需的高度——你就有了额外的空间,因此justify-content
将在你的列上工作。
为什么 Flexbox 中没有justify-self
?
网格布局实现了两个轴的所有属性,因为在网格布局中我们总是有两个轴要处理。 我们创建轨道(这可能会在任一维度的网格容器中留下额外的空间),因此我们可以使用align-content
或justify-content
分配该空间。 我们也有 Grid Areas,那个区域的元素可能不会占满区域的全部空间,所以我们可以使用align-self
或者justify-self
来移动区域周围的内容(或者align-items
, justify-items
更改所有项目的对齐方式)。
Flexbox 不像 Grid 布局那样有轨道。 在主轴上,我们所要做的只是项目之间的空间分布。 没有放置弹性项目的轨道的概念。 所以没有创建用于移动项目的区域。这就是为什么在 Flexbox 的主轴上没有justify-self
属性。
但是,有时您确实希望能够以不同的方式对齐一个项目或一组项目的一部分。 一种常见的模式是拆分导航栏,其中一个项目从组中分离出来。 在这种情况下,规范建议使用自动边距。
自动边距将占据应用方向上的所有空间,这就是为什么我们可以使用 auto 的左右边距使块居中(例如我们的主页布局)。 两边都有自动边距,每个边距都试图占据所有空间,因此将块推到中间。 使用我们的弹性项目行,我们可以将margin-left: auto
添加到我们希望发生拆分的项目上,只要弹性容器中有可用空间,您就会得到拆分。 这与 Flexbox 配合得很好,因为一旦没有可用空间,这些项目就会像常规的弹性项目一样表现。
Flexbox 和微组件
我认为经常被忽视的一件事是 Flexbox 对于做微小的布局工作有多么有用,你可能认为使用vertical-align
是要走的路。 我经常使用 Flexbox 来整齐对齐小图案; 例如,对齐文本旁边的图标,基线对齐两个不同字体大小的东西,或者使表单域和按钮正确排列。 如果您正在努力让一些东西与vertical-align
很好地对齐,那么也许可以尝试使用 Flexbox 来完成这项工作。 请记住,如果需要,您还可以使用display: inline-flex
创建一个内联 flex 容器。
没有理由不使用 Flexbox,甚至 Grid 来完成微小的布局工作。 它们不仅适用于大块布局。 尝试你可以使用的不同的东西,看看什么最有效。
人们通常非常渴望知道做事的正确或错误方式是什么。 在现实中,往往没有对错之分; 您的模式中的微小差异可能意味着 Flexbox 工作得最好的差异,否则您将使用vertical-align
。
包起来
最后,我快速总结了对齐的基础知识。 如果你记住了这几条规则,你应该能够用 CSS 对齐大多数东西:
- 您是对齐文本还是内联元素? 如果是这样,您需要使用
text-align
、vertical-align
和line-height
。 - 您是否有一个或多个项目要在页面或容器的中心对齐? 如果是这样,将容器设置为 flex 容器,然后设置
align-items: center
和justify-content: center
。 - 对于网格布局,以
align-
开头的属性在块方向上起作用; 以justify-
开头的那些在 inline 方向上工作。 - 对于 Flex 布局,以
align-
开头的属性在 Cross Axis 上起作用; 以justify-
开头的那些在主轴上工作。 -
justify-content
和align-content
属性分配额外的空间。 如果您的 flex 或 grid 容器中没有多余的空间,它们将什么也不做。 - 如果您认为在 Flexbox 中需要
justify-self
,那么使用自动边距可能会为您提供所需的模式。 - 您可以将 Grid 和 Flexbox 与对齐属性一起用于小型布局作业和主要组件 — 实验!
有关对齐的更多信息,请参阅以下资源:
- CSS 框对齐(MDN 网络文档)
- 关于 Flexbox 对齐你需要知道的一切
- 框对齐备忘单