标题:How To Center a Div
在很长一段时间里,将元素在其父元素中居中是一件非常棘手的事情。随着 CSS 的发展,我们获得了越来越多的工具来解决这个问题。目前看来,我们的选择多种多样!
我决定创建本教程来帮助你了解不同方法之间的权衡选择,并为你提供可以使用的策略方案,以处理各种场景中的居中。
老实说,这比我最初想象的😅要有趣得多。即使你已经使用CSS一段时间了,我也敢打赌你至少可以学到1个新策略!
使用自动边距居中
我们将要研究的第一个策略亦是最古老的策略之一。如果我们想让元素水平居中,我们可以使用设置为特殊值 auto 的边距来实现:

首先,我们需要约束元素的宽度;默认情况下,Flow 布局中的元素将水平扩展以填充可用空间,我们无法真正将full-width的内容居中。
我可以用固定值来限制宽度(例如。200px),但在这种情况下,我真正想要的是让元素收缩包围其内容。fit-content 是一个神奇的值,正是这样做的。从本质上讲,它使“宽度”的行为类似于“高度”,因此元素的大小由其内容决定。
为什么我设置 max-width 而不是 width?好吧,我的目标是阻止元素水平扩展。我想夹住它的最大尺寸。如果我改用 width,它会将其锁定为该大小,并且当容器非常窄时,元素会溢出。如果将“容器宽度”滑块一直拖动到左侧,则可以看到元素与其容器一起收缩。
现在我们的元素受到了约束,我们可以使用 auto margins 将其居中。
我喜欢将自动边距想象成Hungry Hungry Hippos。每个自动边距都会尝试吞噬尽可能多的空间。例如,看看如果我们only设置margin-left: auto会发生什么:

当 margin-left 是唯一具有自动边距的一侧时,所有 额外空间将作为该侧的边距应用。当我们同时设置 margin-left: auto 和 margin-right: auto 时,两只河马各自吞噬了等量的空间。这会将元素推向中心。
另外: 我一直在使用 margin-left 和 margin-right 因为它们很熟悉,但是有一种更好、更现代的方法去做这个:

margin-inline 会将 margin-left 和 margin-right 设置为相同的值 (auto)。它具有非常好的浏览器支持,几年前就已登陆所有主要浏览器。
逻辑属性
margin-inline不仅仅是margin-left+margin-right的方便简写。它是逻辑属性集合的一部分,旨在使网络国际化变得更容易。在英语中,字符是从左到右写在水平线上的。这些字符被组成单词和句子,并组装成“块”(段落、标题、列表等)。块从上到下垂直堆叠。我们可以将其视为英语网站的方向。
但这并不普遍!有些语言,如阿拉伯语和希伯来语,是从右向左书写的。其他语言(例如中文)历来都是垂直书写的,字符从上到下排列,块从一侧到另一侧排列。
逻辑属性的主要目标是创建一个超越这些差异的抽象。我们可以使用 margin,而不是为从左到右的语言设置 margin-left 并为从右到左的语言将其翻转为
margin-right-内联开始。根据页面的语言,边距将自动应用到正确的一侧。
尽管这种居中方法一直存在,但我仍然发现自己经常使用它!当我们想要将单个子元素居中而不影响其任何兄弟元素时(例如,博客文章中段落之间的图像),它特别有用。
让我们继续我们的居中之旅。
使用 Flexbox 居中
Flexbox 旨在为我们提供大量在沿主轴分布一组项目时的控制能力。它提供了一些真正强大的居中工具!
让我们从水平和垂直居中单个元素开始:

Flexbox 居中最酷的一点是,即使子元素无法放入其容器中,它也能正常工作! 尝试缩小宽度/高度,并注意元素对称溢出。
它也适用于多个孩子。我们可以使用 flex-direction 属性控制它们的堆叠方式:




在本教程中我们将探讨的所有居中模式中,这可能是我使用最多的一种。这是一个很棒的万事通,一个很棒的默认选项。
在视口内居中
到目前为止,我们一直在研究如何将元素在其父容器中居中。但是如果我们想将一个元素置于不同的上下文中怎么办?对话框、提示和 GDPR 横幅等某些元素需要在视口中居中。
这是*定位布局的领域,*是当我们想要将某些内容从流程中取出并将其锚定到其他内容时使用的布局模式。
看起来是这样的:

在我们将讨论的所有策略中,这可能是最复杂的。让我们来分解一下。
我们使用 position: fixed 将此元素锚定到视口。我喜欢将视口想象成位于网站前面的一块玻璃,就像火车的窗户,显示滚动的风景。具有 position: fixed 的元素就像落在窗户上的瓢虫。
接下来,我们设置 inset: 0px,这是设置 top、left、right 的简写,和 bottom 全部设置为相同的值,0px。
仅使用这两个属性,元素将拉伸以填充整个视口,并增长到距每个边缘 0 像素。这在某些情况下可能很有用,但这不是我们在这里想要的。我们需要限制它。
我们选择的确切值将根据每种情况的具体情况而有所不同,但一般来说,我们希望设置默认值(使用 width 和 height)以及最大值( max-width 和 max-height),以便元素不会在较小的视口上溢出。
**这里有一些有趣的事情:**我们设置了一个不可能的条件。我们的元素不能是距左侧 0px 和 距右侧 0px 且 宽度仅为 12rem(假设视口比 12rem 宽)。我们只能选2:


如果我们希望元素距离左边缘为0像素,并且距离右边缘也为0像素,那么它将会延伸到视口的整个宽度,这个宽度比12rem更宽。
**CSS 渲染引擎通过优先级来解决这种紧张。**它将监听width约束,因为这看起来很重要。如果它无法锚定到左侧和右侧,它会根据页面的语言选择一个选项;因此,在像英语这样从左到右的语言中,它将位于左侧边缘。
但是! 当我们将我们的老朋友 margin: auto 带入方程时,有趣的事情发生了。它改变了浏览器解决不可能条件的方式; 它不是锚定到左边缘,而是居中。
而且,与 Flow 布局中的自动边距不同,我们可以使用此技巧将元素水平居中 和 垂直居中。

需要记住的东西很多,但这个技巧有 4 个关键要素。
- 固定定位
- 使用
inset: 0px锚定到所有 4 个边缘 - 约束宽度和高度
- Auto margins自动边距
我们可以使用相同的技巧将某些东西集中在一个方向上。例如,我们可以构建水平居中但锚定在视口底部附近的 GDPR cookie 横幅:

通过省略 top: 0px,我们消除了垂直方向上的不可能条件,并且我们的横幅锚定到底部边缘。作为一个很好的接触,我使用 calc 函数来限制最大宽度,以便元素周围总是有一些缓冲区。
我还将 margin: auto 替换为 margin-inline: auto,这不是绝对必要的,但感觉更精确。
将未知尺寸的元素居中
上述方法要求我们为元素指定一个特定的大小,但是当我们知道它应该有多大时怎么办?
过去,我们必须借助转换技巧来实现这一点,但幸运的是,我们的朋友 fit-content 也可以在这里提供帮助!

这将导致元素围绕其内容收缩。如果我们想约束它,我们仍然可以设置 max-width (例如 max-width: 60vw),但我们不需要需要< /sd3> 设置最大宽度;该元素将自动保留在视口内。
使用 CSS 网格居中
我所知道的水平和垂直居中的最简洁方法是使用 CSS Grid:

place-content 属性是 justify-content 和 align-content 的简写,对行和列应用相同的值。结果是一个 1×1 网格,其中一个单元格位于父容器的中间。
与 Flexbox 的区别
此解决方案看起来非常类似于我们的 Flexbox 解决方案,但请务必记住,它使用完全不同的布局算法。在我自己的工作中,我发现 CSS 网格解决方案并不像 Flexbox 解决方案那样普遍有效。
例如,考虑以下设置: