这是一种水平居中绝对定位元素的有效方法吗?

3

我希望能有一种可重用的方法来水平居中容器内的绝对定位固定宽度元素,同时我需要可重用代码(例如,不使用负像素边距)。

我偶然发现了一个完美的组合:

http://jsfiddle.net/aaronadams/Mquha/

<div class="outer center">
    <div class="inner center"></div>
</div>

.outer {
    position: absolute;
    width: 400px; height: 400px;
    background: #999;
}

.inner {
    position: absolute;
    width: 200px; height: 400px;
    background: #666;
}

.center {
    left: 0; right: 0;
    margin-left: auto; margin-right: auto;
}

这段代码很简洁,(相对)易于理解,看起来能在IE 8+、Chrome、Firefox、Safari上运行……但它似乎也是一个巨大、肮脏、无用的定位hack,可能随时会出现问题。

我找不到任何文档表明这种定位行为是正确还是错误的。它适合生产环境吗?还是完全不可靠?


2
哦,我的天啊!它也适用于垂直居中!o_O - laconbass
1
只要你不需要流式布局,看起来还不错。 - Rajender Joshi
在这个方法中,边距是由渲染引擎自动计算的。这比手动计算更加健壮,因为手动计算会引入更多可能出错的地方。 - Aaron Adams
1
@laconbass 哦,你说得对!http://jsfiddle.net/aaronadams/rkD7h/ 并且感谢Marc Audet在下面的回答中提供的信息,我现在知道该去哪里查找文档了,果然这也是一种记录行为:http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-height 很好的发现。 - Aaron Adams
@cimmanon 这个方法需要设置尺寸,但它们的值对于“居中代码”并不是必要的。 - laconbass
显示剩余2条评论
3个回答

3

假设你的两个容器 .outer.inner 都是绝对定位的,那么你所做的不仅是正确的,而且也是在父容器宽度未指定时唯一的方法。

你的解决方案完全符合 CSS 2.1 规范,非常稳健。

参考资料,请查阅:

http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-width

这段文字讲述了绝对定位元素宽度如何计算。在jsFiddle示例中,需要注意两个
的包含块是视口或根元素。您还没有通过指定top或bottom属性来说明垂直位置。此外,由于绝对定位元素不在流中,它们的固有高度不会影响包含块的高度计算,在某些应用程序中,这是一个因素,如果不进行修改,将使此方法无法使用。另外,如果您将示例代码放入相对定位的包装器
中,并应用固定宽度,则子元素仍将正确居中,如此演示所示: http://jsfiddle.net/audetwebdesign/aNS5j/ (请记住,您可能需要在包装元素中允许足够的高度。)
然而,正如先前在评论中指出的那样,如果包含块的宽度(无论是视口还是我的演示中的包装元素)小于子元素的宽度(在您的示例中为400px),则居中将不再起作用,但这仍然是符合CSS规范的正确行为。
您的问题涉及CSS视觉格式模型工作的基本但重要的基础。
此外
您仍然可以在不使用对.inner元素的绝对定位的情况下获得相同的效果,在这种情况下,“margin: 0 auto”已足够。稍微更简洁的CSS声明可以节省成本。
关于负边距
虽然负边距确实起作用,并且在大多数现代浏览器中实现一致,但CSS 2.1规范并未说明应如何实现负边距。理论上,负边距可能会在一些仍符合CSS规范的用户代理中失效。

谢谢!这正是我在寻找的答案类型:行为文档。我自己找不到它(那些官方的W3C文件对我来说有些难以应付)。显然,这仍需要在大量浏览器上进行测试,但在我的世界里,它可能会证明是一个具有里程碑意义的时间和行数节省者。 - Aaron Adams
1
@AaronAdams 很高兴能帮忙,这是一个好问题,因为它引发了很多有见地的评论。W3C文档很难阅读,就像是由数学家和律师共同编写的,但它们已经导致了符合标准的浏览器,这使我们的行业得以以一种理性的方式发展。祝你好运! - Marc Audet

0

我一直认为,一旦你开始使用position:absolute;,就意味着你放弃了优雅的解决方案。遗憾的是,在很多情况下,绝对定位是解决问题的唯一方法。

据我所知,行业标准是使用负边距,就像你提到的那样:http://jsfiddle.net/Mquha/3/

但这种方法感觉很不好,而且不能重复使用。

我研究了你提出的方法,你的方式似乎是一个相当现代的发现,我有点惊讶它竟然有效。无论如何,它比负边距方法要容易得多,并且似乎被所有主流浏览器支持,就像你说的那样。在未来,我会采用你提出的方法,虽然还不完美,但至少比使用负边距更加干净。我只能建议你在使用绝对定位时也这样做。


你为什么认为绝对定位不够优雅? - laconbass
1
绝对定位仅在内容可预测地小于视口或周围内容时才能很好地居中。 - cimmanon
我个人认为这不够优雅,因为当你使用它时,大多数时间都会破坏页面的流程。@cimmanon,绝对定位几乎总是可预测大小,因此被称为绝对定位。我想知道我的回答有什么值得被踩的地方。 - belens

-1

这是我最好的选择

将你的CSS更改为

#outer {
    position: absolute;
    width: 400px; height: 400px;
    background: #999;
}

#inner {
    position: absolute;
    width: 200px; height: 400px;
    background: #666;
}

.center {
    margin-left: auto; margin-right: auto;
}

并将您的HTML返回

<div id="outer center" class="center">
    <div id="inner center" class="center"></div>
</div>

1
该问题的解决方案实际上是有效的,问题在于它是否适合生产使用。 - laconbass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接