如何让元素(DIV) 居中

2025-03-10
CSS
124

长期以来,将元素置于其父元素的中央是一件非常棘手的事情。随着 CSS 的发展,我们获得了越来越多的工具来解决这个问题。如今,我们有了众多选择!

我决定创建本教程来帮助您了解不同方法之间的权衡,并为您提供一系列可用的策略,以处理各种场景中的居中问题。

老实说,这比我最初想象的要有趣得多。即使你已经使用 CSS 一段时间了,我敢打赌你至少会学到 1 个新策略!

使用自动边距(margin)居中

我们将要研究的第一个策略是最古老的策略之一。如果我们想将元素水平居中,我们可以使用设置为特殊值的边距来实现auto

webfem.com_css_center-a-div_.png

首先,我们需要限制元素的宽度;默认情况下,流布局中的元素将水平扩展以填充可用空间,并且我们无法真正将全宽的东西居中。

我可以用一个固定值(例如)来限制宽度200px,但在这种情况下,我真正想要的是让元素收缩到其内容的周围。fit-content是一个神奇的值,它正是这样做的。本质上,它使“宽度”表现得像“高度”,这样元素的大小就由其内容决定了。

为什么我要设置**max-width**而不是**width**因为我的目标是阻止元素水平扩展。我想限制其最大尺寸。如果我使用width而不是 ,它会将其锁定为该尺寸,并且当容器非常窄时元素会溢出。如果将“容器宽度”滑块一直拖到左侧,您会看到元素随其容器一起缩小。

现在我们的元素受到了约束,我们可以使用自动边距将其居中。

我喜欢将自动边距想象成“ Hungry Hungry Hippos”。每个自动边距都会尝试吞噬尽可能多的空间。例如,看看如果我们只设置会发生什么margin-left: auto

webfem.com_css_center-a-div_ (2).png

margin-left当只有一侧具有自动边距时,所有_额外_空间都会作为边距应用于该侧。当我们同时设置margin-left: auto _和_ margin-right: auto时,两只河马会各自占用相同大小的空间。这会将元素强制置于中心。

另外:我一直在使用margin-leftmargin-right因为它们很熟悉,但是还有一种更好、更现代的方法来做到这一点:

image.png

margin-inline将把margin-left和设置margin-right为相同的值(auto)。它具有非常好的浏览器支持 (在新标签页中打开),几年前就已经登陆各大主流浏览器。

::: 逻辑属性

margin-inline不仅仅是margin-left+ margin-right的便捷简写。它是逻辑属性集合的一部分,旨在让网络国际化变得更加容易。

英语中,字符从左到右以水平线书写。这些字符组成单词和句子,并组装成“块”(段落、标题、列表等)。块从上到下垂直堆叠。我们可以将此视为英语网站的布局。

但这并不普遍!有些语言,如阿拉伯语和希伯来语,是从右向左书写的。其他语言,如中文,历来都是垂直书写的,字符从上到下,_块_从一边到另一边。*

逻辑属性的主要目标是创建一个超越这些差异的抽象。我们可以使用 ,而不是margin-left为从左到右的语言设置 ,并将其翻转为margin-right以适应从右到左的语言margin-inline-start。根据页面的语言,边距将自动应用于正确的一侧。 :::

尽管这种居中方法已经存在很久了,但我仍然发现自己经常使用它!当我们想将单个子元素居中而不影响其任何兄弟元素时,这种方法特别有用(例如,博客文章中段落之间的图像)。

让我们继续我们的学习之旅。

使用 Flexbox 居中

弹性框的设计目的是让我们在沿主轴分布一组项目时拥有极大的控制力。它提供了一些非常强大的居中工具!

让我们从水平和垂直居中单个元素开始:

image.png

Flexbox 居中真正酷的地方在于,即使子元素不适合其容器,它也能正常工作!尝试缩小宽度/高度,并注意元素对称溢出。

它也适用于多个子级。我们可以通过以下属性控制它们的堆叠方式flex-direction

image.png

在本教程中我们将探讨的所有居中模式中,这可能是我使用最多的一种。它是一种万能的绝妙选择,也是一种很棒的默认选项。

在视口内居中

到目前为止,我们一直在研究如何将元素置于其父容器的中心。但是,如果我们想将元素置于不同上下文的中心,该怎么办?某些元素(如对话框、提示和 GDPR 横幅)需要在视口内居中。

这是定位布局的领域,当我们想要将某个东西从流中取出并将其锚定到其他东西上时使用的布局模式。

它看起来是这样的:

image.png

在我们将要讨论的所有策略中,这个策略可能是最复杂的。让我们来分析一下。

我们使用position: fixed,将此元素锚定到视口。我喜欢将视口想象成位于网站前面的一块玻璃,就像火车的窗户,显示滚动的风景。带有 的元素position: fixed就像落在窗户上的瓢虫。

接下来,我们将设置inset: 0px,这是一个简写top,将left、、rightbottom全部设置为相同的值0px

仅使用这两个属性,元素就会拉伸以填充整个视口,并增长到距每个边缘 0px。这在某些情况下很有用,但这不是我们在这里要做的事情。我们需要限制它。

我们选择的确切值将根据每种情况的具体情况而有所不同,但一般来说,我们希望设置默认值(和widthheight以及最大值(max-widthmax-height),以便元素不会在较小的视口上溢出。

这里有一些有趣的事情:我们设置了一个不可能的条件。我们的元素不能距离左侧 0px _,_距离右侧 0px ,并且宽度只有 12rem(假设视口宽度大于 12rem)。我们只能选择 2:

image.png

如果我们希望元素0px从左边缘和0px右边缘开始,它将拉伸到视口的整个宽度,比更宽12rem

CSS 渲染引擎通过优先排序来解决这一矛盾。它会听从width约束,因为这似乎很重要。如果它无法锚定在左侧_和_右侧,它会根据页面的语言选择一个选项;因此,在英语等从左到右的语言中,它将位于左边缘。

但是!当我们把我们的老朋友带入margin: auto方程式时,有趣的事情发生了。它改变了浏览器解决不可能条件的方式;它不再锚定在左边缘,而是将其居中

而且,与_流布局中的自动边距不同,我们可以使用此技巧将元素水平和_垂直居中。

image.png

要记住的东西很多,但是这个技巧有 4 个关键要素。

  1. 固定定位

  2. 锚定在所有 4 个边缘上inset: 0px

  3. 宽度和高度受限

  4. 自动边距

我们可以使用相同的技巧将某些内容集中在一个方向上。例如,我们可以构建一个水平居中但固定在视口底部附近的 GDPR cookie 横幅:

image.png

通过省略top: 0px,我们消除了垂直方向上的不可能条件,并且我们的横幅固定在底部边缘。作为一个不错的设计,我使用了calc函数来限制最大宽度,以便元素周围始终有一点缓冲。

我还将其换成了margin: automargin-inline: auto这不是绝对必要的,但感觉更精确。

使大小未知的元素居中

上面描述的方法要求我们赋予元素一个特定的大小,但是当我们不知道_它_应该有多大时该怎么办?

过去,我们不得不借助于变换黑客来实现这一点,但幸运的是,我们的朋友fit-content也可以在这里提供帮助!

image.png

这将导致元素在其内容周围收缩。max-width如果我们想限制它,我们仍然可以设置一个(例如max-width: 60vw),但我们不需要设置最大宽度;元素将自动保持在视口内。

使用 CSS 网格居中

我知道的最简洁的水平和垂直居中的方法是使用 CSS Grid:

image.png

该属性是和place-content的简写,将相同的值应用于行和列。结果是一个 1×1 网格,单元格位于父容器的中间。justify-content`align-content`

与 Flexbox 的区别

此解决方案与我们的 Flexbox 解决方案非常_相似_,但请务必记住,它使用完全不同的布局算法。在我自己的工作中,我发现 CSS Grid 解决方案并不像 Flexbox 解决方案那样普遍有效。

例如,考虑以下设置:

image.png

很奇怪吧?为什么 CSS Grid 版本变得这么小?!

情况是这样的:子元素被赋予width: 50%height: 50%。在 Flexbox 中,这些百分比是根据父元素计算的,.container这正是我们想要的。

然而,在 CSS Grid 中,百分比是相对于网格单元的。我们说子元素的宽度应为其列的 50%,高度应为其行的 50%。

现在,我们实际上还没有给行/列指定一个明确的大小;我们还没有定义grid-template-columnsgrid-template-rows。当我们忽略这些信息时,网格轨道将根据其内容计算其大小,收缩包裹每行/列中的所有内容。

最终结果是我们的网格单元与的原始尺寸相同.element,然后元素缩小到该网格单元的 50%:

image.png

这简直就是个兔子洞,我不想离题太远;我的观点是,CSS Grid 是一种复杂的布局算法,有时,额外的复杂性会造成阻碍。我们_可以_添加更多 CSS 来修复此代码,但我认为使用 Flexbox 更简单。

将一堆元素居中

CSS Grid 为我们提供了另一个居中超能力。使用 CSS Grid,我们可以将多个元素分配给同一个单元格:

image.png

我们仍然有一个 1×1 的网格,只是现在我们要用/将_多个_孩子塞进那个单元格中。grid-row`grid-column`

如果不清楚的话,下面是此类设置的 HTML 简要草图:

Copy to clipboard

<div class="container">  <img class="element" />  <img class="element" />  <img class="element" />  <img class="element" /></div>

在其他布局模式下,元素会水平或垂直堆叠,但使用此 CSS Grid 设置,元素会从后到前堆叠,因为它们都被告知共享相同的网格空间。很酷,对吧?

令人难以置信的是,即使子元素大小不同,这也能起作用!看看这个:

image.png

在此演示中,添加了红色虚线以显示网格行和列。请注意,它们会扩展以包含最大的子元素;添加所有元素后,生成的单元格与粉红色天际线图像一样宽,与彩色空间图像一样高!

我们确实还需要一个属性来实现这一点:place-items: center.是和place-items的简写,这些属性控制网格单元_内_图像的对齐方式。justify-items`align-items`

如果没有此属性,网格单元仍然会居中,但该单元内的图像将全部堆叠在左上角:

image.png

这是相当高级的东西!

居中文本

文本在 CSS 中是独一无二的。我们无法使用本文探讨的技术来影响单个字符。

例如,如果我们尝试使用 Flexbox 将一个段落居中,我们将使文本块居中,而不是文本本身:

image.png

Flexbox 将段落置于视口的中心,但不会影响单个字符。它们保持左对齐。

我们需要使用text-align来使文本居中:

image.png

何时使用哪种方法

在结束之前,让我们通过构建一种决策树来总结一下我们所学到的知识,以便我们能够确定何时使用哪种方法。

  • 如果我们想要水平居中单个元素而不干扰其任何兄弟元素,我们可以使用流布局自动边距策略。

  • 如果我们有一个浮动的 UI,比如模式或横幅,我们可以使用定位布局和自动边距将其居中。

  • 如果我们想将一堆元素一个接一个地居中放置,我们可以使用CSS Grid。

  • 如果我们想让文本居中,可以使用text-align。这可以与任何其他方法结合使用。

  • 最后,在大多数其他情况下,我们可以使用Flexbox。它是最通用的方法;它可用于将一个或多个子元素水平和/或垂直居中,无论它们是包含的还是溢出的。

希望您在这里学到了一些新策略!祝您居中愉快。❤️

翻译自:https://www.joshwcomeau.com/css/center-a-div/

原文地址:https://webfem.com/post/div-center,转载请注明出处