固定div的CSS水平居中?

245
#menu {
    position: fixed;
    width: 800px;
    background: rgb(255, 255, 255); /* The Fallback */
    background: rgba(255, 255, 255, 0.8);
    margin-top: 30px;
}
我知道这个问题已经问了无数遍,但我找不到适用于我的情况的解决方案。 我有一个div,应该固定在屏幕上,即使页面被滚动也应始终保持在屏幕的中心位置!
div应该有500px宽度,距离顶部应该有30px的距离(margin-top),对于所有浏览器大小都应水平居中,并且在滚动页面时不应移动。
这是否可能?

请参见https://dev59.com/-GQn5IYBdhLWcg3wIkMF - Déjà vu
9个回答

787

这里的答案已经过时了。现在您可以轻松地使用CSS3 transform而不用硬编码一个margin。这适用于所有元素,包括没有宽度或动态宽度的元素。

水平居中:

left: 50%;
transform: translateX(-50%);

垂直居中:

top: 50%;
transform: translateY(-50%);

水平和垂直方向均可:

left: 50%;
top: 50%;
transform: translate(-50%, -50%);

兼容性不是问题:http://caniuse.com/#feat=transforms2d


您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Jessica
4
这会在内容元素的盒子阴影中产生模糊效果。 - rab
5
Chrome浏览器会错误地模糊被变形的内容,包括文本。但这是唯一的解决方案,可以将固定元素居中而无需硬编码或使用包装元素。如果您不关心背景的指针事件,可以使用全屏包装和flexbox或@salomvary下面的解决方案来实现相同的效果。 - Maciej Krawczyk
这似乎在居中元素上设置了一个最大宽度,这以前并没有。我正在使用此功能来使固定的Bootstrap面板居中,并且它强制将宽度缩小到比以前更小。有没有办法克服这个问题?内容是动态的(我的表单操作按钮),所以我不能硬编码宽度。 - Sam Jones
1
这个工作得很好,但我想要居中的元素已经有一个动画了,它会执行 translateX(-50%)... - dguay
1
这将防止您拥有一个“固定”位置的子元素。 - Emperor Eto

166
left: 50%;
margin-left: -400px; /* Half of the width */

3
你确定吗?在调整大小时它看起来对我没问题。我认为这个“-400”是由于div的宽度设置为“800”。 - Merlyn Morgan-Graham
1
@Quentin,这种方法与使用转换相比没有任何优势,并且使用范围有限。使用转换会更好,也是更好的实践。在响应式时代,教人们硬编码这些值是不好的实践。我同意在2010年这是正确的答案,但现在已经不是了。 - Preston Badeer
9
完全同意 - 这不是一个解决方案!永远不要以这种方式硬编码某些东西。-1 - Nate I
1
@NateI — 这个答案是半个多十年前的,当时浏览器对更好的替代方案的支持非常差。 - Quentin
4
我投反对票并非因为那是个不好的答案-它曾经是个好答案,但现在不再是了。而排名第二的回答需要尽可能多的帮助才能被认为是最佳答案。Quentin建议在答案本身中编辑一条评论以表明这种情况,这样我会撤销我的反对票。 - Nick Rice
显示剩余5条评论

61

如果可以使用内联块,则我建议采用以下方法:

.container { 
    /* fixed position a zero-height full width container */
    position: fixed;
    top: 0; /* or whatever position is desired */
    left: 0;
    right: 0;
    height: 0;
    /* center all inline content */
    text-align: center;
}

.container > div {
    /* make the block inline */
    display: inline-block;
    /* reset container's center alignment */
    text-align: left;
} 

我在这里写了一篇简短的文章:http://salomvary.github.com/position-fixed-horizontally-centered.html


1
非常好,这对我非常有用,而且不需要为“宽度”或其他东西硬编码任何数字——不像@Quentins的答案。 - Yatharth Agarwal

39

2016年9月修订:尽管偶尔还能获得一些赞,但由于时代变迁,我现在会选择使用使用transform的答案(有很多赞)。我不会再这样做了。

另一种不需要计算边距或需要子容器的方法:

#menu {
    position: fixed;   /* Take it out of the flow of the document */
    left: 0;           /* Left edge at left for now */
    right: 0;          /* Right edge at right for now, so full width */ 
    top: 30px;         /* Move it down from top of window */
    width: 500px;      /* Give it the desired width */ 
    margin: auto;      /* Center it */
    max-width: 100%;   /* Make it fit window if under 500px */ 
    z-index: 10000;    /* Whatever needed to force to front (1 might do) */
}

@Joey 底部的:0是什么作用?即为什么需要它?(我很久没看过这个了!) - Nick Rice
bottom:0 会确保菜单始终垂直居中,但我现在看到这不是 OP 所要求的。 :) - Jordan H
我尝试在不同的上下文中使用它,但发现如果元素的高度大于窗口(视口)的高度,则它在FF中无法居中。 - Philipp Werminghausen
因为世界已经发生了变化,所以我现在会选择使用 transform 的答案。(之前我曾在评论中提到过回答者使用的名称 - 但他们更改了那个名称,所以我的评论不再有意义,我将其删除 - 只需在此页面上搜索 transform 即可找到答案。) - Nick Rice

10
可以使用以下方法水平居中div:
html代码如下:
<div class="container">
    <div class="inner">content</div>
</div>

CSS:

.container {
    left: 0;
    right: 0;
    bottom: 0; /* or top: 0, or any needed value */
    position: fixed;
    z-index: 1000; /* or even higher to prevent guarantee overlapping */
}

.inner {
    max-width: 600px; /* just for example */
    margin: 0 auto;
}

使用这种方法,您将始终使内部块居中,此外它可以轻松地变为真正的响应式(在示例中,它只会在较小的屏幕上变为流体),因此没有限制,就像问题示例和所选答案一样。

正是我所需要的:一个居中且固定的块。 - Marco

7

这是另一种两个 div 的解决方案。尝试保持简洁且不硬编码。首先,可预期的 html 代码:

<div id="outer">
  <div id="inner">
    content
  </div>
</div>

以下css的原理是定位"outer"的某些侧面,然后利用它假设"inner"的大小来相对移动后者。
#outer {
  position: fixed;
  left: 50%;          // % of window
}
#inner {
  position: relative;
  left: -50%;         // % of outer (which auto-matches inner width)
}

这种方法与Quentin的方法类似,但inner可以是可变大小的。

5

您可以将菜单div包裹在另一个div中:

    <div id="wrapper">
       <div id="menu">
       </div>
    </div>


#wrapper{
         width:800px;
         background: rgba(255, 255, 255, 0.8);
         margin:30px auto;
         border:1px solid red;
    }

    #menu{
        position:fixed;
        border:1px solid green;
        width:300px;
        height:30px;
    }

-1
div {
   left: calc((100vw - 100%) / 2);
}

1
你的回答可以通过添加更多关于代码的信息以及它如何帮助提问者来改进。 - Tyler2P

-1
这是一个关于编程的内容,以下是翻译文本:

在使用全屏包装器div时,这是一个flexbox解决方案。justify-content可以让子div水平居中,而align-items可以让其垂直居中。

<div class="full-screen-wrapper">
    <div class="center"> //... content</div>
</div>

.full-screen-wrapper { 
  position: fixed;
  display: flex;
  justify-content: center;
  width: 100vw;
  height: 100vh;
  top: 0;
  align-items: center;
}

.center {
  // your styles
}

1
这个解决方案的问题在于它使得空白区域(div 左右两侧)中的任何内容都无法被点击。 - Burawi
好观点 @Burawi - 谢谢。 - undefined

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