在 CSS 中居中元素是 CSS 吐槽的典型代表。为什么它必须如此困难? 他们嘲讽道。我认为问题不在于它难以实现,而在于有太多不同的方法可以实现它,具体取决于情况,很难知道该选择哪一种。
所以让我们把它变成一棵决策树,希望能够简化操作。
我需要居中…
水平方向
它是内联元素还是内联-*元素(如文本或链接)?
您可以使用以下方法水平居中内联元素,在块级父元素内:
.center {
text-align: center;
}
这适用于内联、内联块、内联表格、内联弹性盒等。
它是一个块级元素吗?
您可以通过为块级元素设置margin-left
和margin-right
为auto
来居中(并且它具有设定的width
,否则它将是全宽并且不需要居中)。这通常使用以下简写方式完成
.center-me {
margin: 0 auto;
}
无论您要居中的块级元素的宽度或父元素如何,这都适用。
请注意,您不能将元素float
到中心。不过有一个技巧。
是否有多个块级元素?
如果您有两个或多个需要水平一行居中的块级元素,则您最好将它们设置为不同的display
类型。这是一个将它们设置为inline-block
的示例,以及一个flexbox的示例
除非您的意思是您有多个垂直堆叠的块级元素,在这种情况下,自动边距技术仍然适用
垂直方向
在 CSS 中,垂直居中稍微复杂一些。
它是内联元素还是内联-*元素(如文本或链接)?
它是一行吗?
有时,内联/文本元素可能看起来是垂直居中的,仅仅是因为它们的上方和下方有相等的填充。
.link {
padding-top: 30px;
padding-bottom: 30px;
}
如果由于某种原因填充不是一种选择,并且您试图居中一些您知道不会换行的文本,则有一个技巧是使line-height
等于高度,这将center
文本。
.center-text-trick {
height: 100px;
line-height: 100px;
white-space: nowrap;
}
它有多行吗?
顶部和底部的相等填充也可以为多行文本提供居中效果,但如果这不起作用,也许包含文本的元素可以是表格单元格,无论是字面上的还是使用 CSS 使其表现得像一个表格单元格。vertical-align
属性处理这种情况,在这种情况下,与它通常处理一行上对齐的元素的对齐方式不同。(更多信息。)
如果表格式方法不可行,也许您可以使用flexbox?可以很容易地使单个flex-child在flex-parent中居中。
.flex-center-vertically {
display: flex;
justify-content: center;
flex-direction: column;
height: 400px;
}
请记住,只有当父容器具有固定高度(px、% 等)时,这才是真正相关的,这就是为什么此处的容器具有高度的原因。
如果这两种技术都不可行,您可以采用“幽灵元素”技术,其中一个全高伪元素放置在容器内,并且文本与此伪元素垂直对齐。
.ghost-center {
position: relative;
}
.ghost-center::before {
content: " ";
display: inline-block;
height: 100%;
width: 1%;
vertical-align: middle;
}
.ghost-center p {
display: inline-block;
vertical-align: middle;
}
它是一个块级元素吗?
您知道元素的高度吗?
在网页布局中,不知道高度的情况相当常见,原因有很多:如果宽度发生变化,文本重排可能会改变高度。文本样式的变化可能会改变高度。文本数量的变化可能会改变高度。具有固定纵横比的元素(如图像)在调整大小时可能会改变高度。等等。
但是,如果您知道高度,则可以像这样垂直居中
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
height: 100px;
margin-top: -50px; /* account for padding and border if not using box-sizing: border-box; */
}
元素的高度未知吗?
仍然可以通过在向下移动一半高度后将其向上移动一半高度来居中它
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
您是否关心元素是否会拉伸容器的高度?
如果您不关心,您只需要将内容垂直居中,使用表格或 CSS 显示将元素变成表格可以解决问题。
您可以使用flexbox吗?
毫不奇怪,这在flexbox中容易得多。
.parent {
display: flex;
flex-direction: column;
justify-content: center;
}
您还可以使用子元素上的margin: auto;
在flexbox中实现居中。
水平和垂直方向
您可以以任何方式组合上述技术来获得完美居中的元素。但我发现这通常分为三大类
元素的宽度和高度是固定的吗?
在您将其绝对定位在 50% / 50% 之后,使用等于该宽度和高度一半的负边距可以将其居中,并具有良好的跨浏览器支持
.parent {
position: relative;
}
.child {
width: 300px;
height: 100px;
padding: 20px;
position: absolute;
top: 50%;
left: 50%;
margin: -70px 0 0 -170px;
}
元素的宽度和高度未知吗?
如果您不知道宽度或高度,则可以使用transform属性和两个方向上的负translate 50%(它基于元素的当前宽度/高度)来居中
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
您可以使用flexbox吗?
要使用flexbox在两个方向上居中,您需要使用两个居中属性
.parent {
display: flex;
justify-content: center;
align-items: center;
}
您可以使用网格吗?
这只是一个小的技巧(由 Lance Janssen 发送),它几乎适用于一个元素
body, html {
height: 100%;
display: grid;
}
span { /* thing to center */
margin: auto;
}
结论
您完全可以在 CSS 中居中元素。
好主意!我喜欢这篇文章的概念以及显示/隐藏结构。我赞扬你,先生。
但是,我认为您在几个地方错过了经典“居中很难”抱怨背后的精神,至少对我来说,它总是回到不知道元素的高度。
1) 您的 display: table-cell 修复依赖于知道子元素的高度。
2) 在您的“它是块级元素” -> “元素的高度未知”中,您继续为父元素设置显式高度。对我来说,这违背了尝试处理未知高度场景的目的。如果我不知道子元素的高度,我通常也不知道父元素的高度。
3) 在您的“水平和垂直方向示例”中,当高度未知时,让子元素为 pos: absolute 并暗示这无关紧要有点奇怪。我认为 pos: absolute 是布局时的主要注意事项,因为它可能会意外地导致元素相互覆盖。
4) 此外,在同一个示例中,如果元素有一个拉伸父元素垂直高度的兄弟元素,则该元素无法保持垂直居中。
无论如何,我仍然非常喜欢这个想法——它非常需要。我只是认为,如果您承认我认为是您试图驳回的抱怨根源的一些注意事项,它将得到改进。
1) 它实际上没有。我更新了 示例,在表格上设置高度。
2) 垂直居中只有在父元素具有设置高度时才相关。如果父元素没有设置高度,那么您在什么范围内居中?即使答案是“整个页面”,那么您也需要设置(可能)
html, body
的高度3) 这是公平的。这只是一个例子。根据我的经验,如果您试图以这种方式同时居中某些东西,它可能是一个模态窗口,在这种情况下将使用绝对(或固定)定位。如果不是,您可以根据需要组合任何其他技术。而且总有flexbox,我已经介绍了很多。
4) 在这个方面给我演示一下?我很难想象/重现。
嘿,Chris!感谢您的回复。
关于 #1:我觉得我们在这个问题上没有理解彼此。当我查看示例时,我做的第一件事是删除 HTML 表格,因为这对于我的大多数用例来说都不切实际/不理想,尽管也许我在这里对表格过于反感。无论如何,这留下了 div html,它确实具有显式高度,这就是垂直居中的动力。结果:http://codepen.io/anon/pen/xIvqh
关于 #2:实际上,我和您刚刚语气严厉地回复的评论者在同一轨道上。假设我想垂直居中两个不同高度的内联块兄弟元素:http://codepen.io/anon/pen/Cjdeo
关于 #3:休战。
关于 #4:实际上与 #2 是一样的观点,尽管我没有注意到 pos: absolute 也是其中的一部分,这确实分散了对高度问题的注意力(元素相互覆盖的事实比它们没有垂直居中更引人注目的布局错误):http://codepen.io/anon/pen/rjflG。
抱歉,我对#1中你正在做的事情有点误解,错误地表达了你的意思。就此休战,也罢。
很棒的技巧!
我尝试在我的响应式模板中应用其中的一些。但在这里它没有按预期工作。问题是
1. 我有4个浮动div
在响应式部分,框的宽度设置为49%或100%,所有框都向左浮动。
我试图使所有框的高度相同。在页面全宽的情况下,样式
工作正常。但在较窄的显示器上,框的响应性被忽略,它们始终保持一行4个。
这里哪里出错了?
你也可以这样使用绝对定位
查看CodePen上的sodawillow的笔垂直边距:自动 (@sodawillow)。
前段时间我收集了24种不同的“使用css居中”案例
http://ksesocss.blogspot.com/2012/05/centrando-al-centro-con-css-16-maneras.html
西班牙语博客,但代码是代码
这样做有多好?
它在Opera中运行得不太好,但我喜欢这个概念。
http://codepen.io/sodawillow/pen/yqnaC/ :-p 似乎在这里(win)的Opera中可以工作 :)
是的!当然...
我忘记了一件事:使用
min-height
代替。没有固定高度不起作用。谢谢
只想为任何需要的人添加灯箱(绝对)水平居中
http://codepen.io/bradwestfall/pen/CBcKy
让父元素为display:table;并将子元素设为display:table-cell;vertical-align:middle;也在潜在解决方案中占有一席之地。
谢谢!我打算经常使用它 :)
当使用transform属性和两个方向上的负translate 50%(当水平和垂直居中宽度和高度未知的元素时)时,问题是当-50%的结果不是整数时,结果通常会变得模糊(取决于第一个具有非静态位置的父元素的确切大小)。
我想在视网膜屏幕上模糊是不可见的,但在大多数人的屏幕上它很糟糕:/
同意。我不喜欢在基于文本的内容上使用转换。浏览器在渲染方面已经变得更好,但你仍然经常会得到模糊、难以阅读的文本。
显然,通过向父元素添加preserve-3d可以修复。
考虑到这篇文章被称为完整指南,我希望阅读更多关于常见问题的信息,例如浮动的居中、在多行列表元素中对齐列表元素图标等,而不是阅读关于不切实际的flexbox内容。
但要回答这个问题:“如果父元素没有设置高度,你在哪里居中?” 由其最高的子元素扩展的容器,其他子元素需要在其内垂直对齐,这很明显。
因语气而被隐藏。
一个隐藏完全合理的评论的糟糕理由。
Chris - 你可能想添加,要水平居中使用margin: 0 auto; 的块级元素,它必须具有固定大小。你没有特别提到这一点。
没有必要,因为块级元素默认情况下是全宽的,当它们填充整个可用空间时不需要水平对齐。
没有关于vertical-align的内容,是吗?有史以来最没用的属性。
为什么?为什么在固定高度的块中居中一些内容如此令人困惑、困难且需要hack?我仍然不明白。我太累了。我太累了。
在垂直 -> 多行下提到了它。
但绝对同意这个过程比它应该的要笨拙得多!这个概念非常基础,但看看我们有多少潜在的解决方案……
优秀的指南!不过一个小错误:你在垂直 > 内联 > 单行下使用了“were”而不是“where”。
你可以添加垂直“translate”hack的“半像素”修复,http://zerosixthree.se/vertical-align-anything-with-just-3-lines-of-css/(2014年4月的更新)
啊,我刚刚写了关于该死的模糊内容。感谢这个有用的评论!
感谢您提供半像素修复的链接。我总是试图通过确保我的行高和所有填充都以像素和偶数表示来避免它(这样高度总是偶数)。但你给出的修复使这变得容易得多。
完整的指南非常有用。非常感谢您提供这个出色且清晰的概述!已收藏:-)
另一种水平居中未知宽度元素(例如
<button>
)的方法,无需依赖父元素尽管我发现它是最优雅的解决方案,但使用translate(-50%)进行垂直定位会在Windows上的Chrome(多个版本)中产生模糊内容。
精彩的总结,Chris。直接进入我的CSS书籍的网页目录。
顺便说一句,投诉部分原因是“”太简单了,而“margin: 0 auto”是一个如此笨拙的方法。这仍然是CSS最糟糕的地方。
如果我需要居中一个动态内容宽度的div,我不能使用
margin: 0 auto
技巧。在这种情况下,我是否应该将其转换为display: inline-block
元素?如果该解决方案不可行怎么办?DIV不会缩小以适应(除非浮动),因此,如果你不添加宽度,它将始终是全宽,你不需要水平居中。所以,无论如何你都必须添加宽度。或者像你已经说过的使用inline-blick。
你也可以对多行使用行高技巧,并且它具有更好的浏览器支持 -
http://codepen.io/seanjacob/pen/xjAnD
实际上,这只是一行/容器,里面有多行。如果你想要多行/容器,它就会失效。
你能给我举个例子吗?如果你想要多个容器,你应该将它们放在
.middle
元素中,而不是创建多个.middle
元素。仅供参考,也许CSS固有大小可能是块级元素水平居中的(未来)替代方案?
将来,当然可以。目前,浏览器对
width
的固有大小的支持还不错,但对height
上的fit-content
的支持很糟糕。如果你能回顾一下每种方法的浏览器兼容性,那就太好了!
我整理了一个表格,比较了不同方法的浏览器兼容性,还包括一些未提及的方法。请查看 http://codepen.io/shshaw/full/gEiDt/ 中的“比较表格”。
这些方法大多数都应该在 IE8+ 中工作,但变换(transforms)只在 IE9+ 中有效。在“其他技巧”部分可以找到有关每种技术的更多信息。
很棒的总结。惊讶的是没有提到使用
margin: auto
作为固定宽度/高度的解决方案:-)在你的“幽灵居中”示例中,在垂直 > 内联 > 多行下,它之所以在这里能正常工作,是因为你为要居中的内联元素设置了固定宽度。
由于它们都是
display: inline-block
,浏览器会自动在它们之间添加空格。如果移除固定宽度,你的内容最终会被::before
元素向下推。http://codepen.io/shshaw/pen/bfvHt
一种更安全的方法是使用
::after
代替。这样,实际内容就不会被伪元素向下推。你也可以移除内容的固定宽度,并使用
letter-spacing: -0.5em
来防止伪元素和要居中元素之间出现间隙。然后在居中元素上使用letter-spacing: normal
重置。http://codepen.io/shshaw/pen/huzer
嘿,Chris。这是一个很棒的资源。我认为如果添加一些关于何时使用哪种方法的基本指南会非常有用。这主要与浏览器兼容性有关,我认为很多人对这方面比较模糊。也许可以创建一个矩阵,你在其中勾选你想要支持的浏览器,然后只突出显示相关的方法。
我有一些关于如何使用本文作为基础来实现此功能的想法……我应该开始写博客了。
这对我帮助很大。但是,我仍然难以在一行中居中多个div。如果你有时间,请查看我的网站(我刚开始学习网页开发,所以不要太苛刻)我的网站,看看页面顶部的5个圆圈……目前,它们没有水平居中(一侧的空白空间比另一侧多),我想知道你是否知道如何解决这个问题,以便所有内容都页面上居中。感谢你的时间。
精彩的文章!
使用
display: flex;
使各种列高度相同的方法非常简单!希望至少能支持 IE 9。
有人知道一个简单的“回退”方案吗?
天哪!
transform: translate(-50%, -50%);
真是太棒了……我简直不敢相信我从未想过这个方法。我之前不知道它得到了如此广泛的支持。生活变得更好了:-)
感谢 Chris 提供如此有用的指南!
先生,你值得一个赞!
我个人在使用margin时从未使用过值“0”。我一直使用
margin:auto;
,仅此而已。我从未遇到过任何问题,因为省略了那个0。只是说说而已。
很棒的决策树想法!
我非常喜欢这个网站!我通过访问这里解决了了许多CSS问题!谢谢Chris!
嗨,Chris,一如既往,文章很棒,非常有用!
小心,CodePen示例从一个分支/段落转移到另一个分支/段落(例如:幽灵元素示例应该在垂直/内联/多行中,但实际上位于垂直/块/你知道高度中)。
干杯,Pierre
组织良好的文章。**CSS中的居中**一直是Web开发人员的痛点。这份指南对他们来说是救星!
我一直使用
line-height
来垂直对齐文本。否则,我想在页面加载时使用JavaScript对齐元素;-)但这并不是正确的方法!感谢这篇文章!非常感谢你提供的宝贵信息。对于CSS初学者来说,这是一篇必读的文章。
“元素的宽度和高度未知吗?”——我更喜欢使用表格的防弹老式解决方案 http://codepen.io/andychups/pen/CDLxK。
顺便说一句,我喜欢这条推特:“在CSS中垂直居中某个东西最简单的方法是合上你的笔记本电脑去酒吧。” @bleikamp
:)
嗨,Chris,
你知道是否有任何选项可以根据文本的x高度而不是文本的整个高度来垂直居中文本?当容器略大于字体大小时,这可能是首选。
我想到的唯一选项只适用于单行文本,包括添加一个伪元素,其高度设置为其容器的高度,并应用
vertical-align: middle;
。请查看 http://codepen.io/ckuijjer/pen/nIGCt
很酷的东西,我喜欢阅读你的博客
不错。总是有很多不同的选择,但我认为让人沮丧的是,没有一种万无一失的方法可以在浏览器支持良好的情况下垂直居中某个东西,而不会添加某种额外的标记。无论我最终选择哪种方法,都感觉有点像hack和脏东西,但我猜垂直居中并非独此一家。
如果父元素的高度已知,我通常会将其作为父元素上的行高,并将子元素设置为内联块,这样子元素的高度可以是可变的。如果父元素的高度未知,我通常会绝对定位子元素并根据需要移动它。
感谢你的提示,我也喜欢这种方法,它也适用于IE8
http://codepen.io/anon/pen/CmlDL
它基于内联块和伪元素的使用。
用于垂直居中的行高选项效果很好。
但是,我不明白何时使用
min-height
。如果我为顶部的一个全宽工具栏设置了固定高度和行高,响应式布局会出现问题吗?感谢你的教程!