Web编程技术营地
研究、演示、创新

垂直水平居中标签

撰写时间:2025-03-08

修订时间:2025-12-21

这里集中列出使用CSS在垂直及水平方向上居中放置标签的各种方案。

flex

#container { width: 100px; height: 100px; background: #2F3F3F; display: flex; justify-content: center; align-items: center; } #child { width: 50px; height: 50px; background: darkcyan; }

grid

#container { width: 100px; height: 100px; background: #2F3F3F; display: grid; place-items: center; } #child { width: 50px; height: 50px; background: darkcyan; }

grid还可通过在子标签中设定margin: auto的方式来快速实现垂直与水平居中。

#container { width: 100px; height: 100px; background: #2F3F3F; display: grid; } #child { margin: auto; width: 50px; height: 50px; background: darkcyan; }

absolute + transform

#container { width: 100px; height: 100px; background: #2F3F3F; position: relative; } #child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 50px; height: 50px; background: darkcyan; }

absolute根据父容器的值来调整位置,而transform则再根据自身的大小来调整位置。

absolute + margin

#container { width: 100px; height: 100px; background: #2F3F3F; position: relative; } #child { position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; width: 50px; height: 50px; background: darkcyan; }

加入fit-content属性值,也可适用于自身本无大小、但需要根据自身内容来设置大小的标签,例如p, span等。

#container { width: 100px; height: 100px; background: #2F3F3F; position: relative; } #child { position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: auto; width: fit-content; height: fit-content; color: #FFF; padding: 1em; background: darkcyan; }

Hello

table

#container { background: #2F3F3F; display: table; padding: 1em; } #child { display: table-cell; vertical-align: middle; text-align: center; width: 50px; height: 50px; background: darkcyan; }

对于使用display: table的标签,没必要设置尺寸大小,而应在该标签内设置padding属性,然后再在使用display: table-cell的标签中设置大小。这样,表格的大小就能从内到外通过计算自动设定。

line-height + inline-block

#container { width: 100px; height: 100px; background: #2F3F3F; line-height: 100px; text-align: center; } #child { width: 50px; height: 50px; display: inline-block; vertical-align: middle; margin-top: -5px; background: darkcyan; }

先在父容器设置line-height,再在子标签设置display: inline-block,则可像设置字符一样安排其垂直方向的对齐方式。

由于子标签确实没有文本的基线 (baseline) 等基本特征,因此默认情况下不能在垂直方向上精准地对齐,此时可使用margin-top来进行细微调节。

应用篇

居中正方形子容器

本例中,我们在整个客户端中自动居中放置一个正方形的子容器。

最简单的方式。

:root { --top-margin-value: 20px; } div { height: calc(100vh - var(--top-margin-value) * 2); margin: var(--top-margin-value) auto; aspect-ratio: 1 / 1; background-color: #2F3F3F; }

这种方式只需指定子容器上边距的值,然后自动计算出其heightmargin属性值,即可自动居中。

下面为较完善的方式。

html, body { margin: 0; padding: 0; border: 0.5px solid green; box-sizing: border-box; min-height: 100vh; display: grid; } div { margin: auto; width: calc(min(100vw, 100vh) * 0.8); aspect-ratio: 1 / 1; box-sizing: border-box; border: 5px solid gray; background: #2F3F3F; }

htmlbodymarginpadding均设为0,再将其最小高度min-height设置为整个客户端的高度。使用min-height而不是height的原因在于,当子容器的高度大于客户端的高度时,允许htmlbody的高度值被自动拉伸。

子容器div的宽高比为1,因此只需计算一个width属性值即可。

从客户端的宽度值与高度值中取最小值,可确保子容器的内容不会超出客户端的范围。将此值乘以缩放因子0.8,则在父容器与子容器之间自动产生一个1 - 0.8 = 0.2em的留白。

如果缩放因子在某些情况下必须大于1.0,则将divmargin属性值改为margin: 1em auto,则可在自动左右居中的同时,在上下两端留出特定的留白。

将子标签高度限制在视口内

在桌面应用程序中,应用程序的内容被限定在窗口的范围内。当窗口高度变小时,窗口可能会出现垂直滚动条,从而可以通过滚动条来查看所有内容。

而在HTML网页中,body的高度值仅受其子元素的高度值的影响,不受视口高度值的影响。因此,如果我们打开浏览器的检查器,视口区域将变小,但body所占据的空间仍自动扩展,从而使得其内容始终无法被限定在相对固定的视口范围内。本节实现此目的。

在一个单页 (single page) 的 Web app 中,我们希望将整个内容都限制在视口范围内。

Grid

首先,查看默认状态。

:root { color-scheme: light dark; } html, body { margin: 0; padding: 0; } html { box-sizing: border-box; border: 1px solid red; height: 100vh; > body { border: 5px solid green; margin: 1em; > div { height: 100px; border: 5px solid blue; } } }

Auto-fit in Maximized Viewport

This is a paragraph.

上面输出面板的高度值由LiveEditor在内部设置为300pxhtml的高度值为100vh,则代表其高度的红色边框正好铺满整个视口。因此红色边框的高度可视为视口高度。

由于此时body中的内容较少,代表其高度的绿色边框自动包裹住其最后一个子元素(蓝色边框)。

我们的目标是,让body的绿色边框随html的红色边框而变。要实现此目标,将html设置为Grid即可。

:root { color-scheme: light dark; } html, body { margin: 0; padding: 0; } html { box-sizing: border-box; border: 1px solid red; height: 100vh; display: grid; > body { border: 5px solid green; margin: 1em; > div { height: 100px; border: 5px solid blue; } } }

Auto-fit in Maximized Viewport

This is a paragraph.

现在,由于html成为Grid容器,则其所有空间均成为Grid的弹性空间。且由于html下面只有body一个直接子元素,故body的高度可随html的高度而变化。故绿色边框紧贴着红色边框。

将输出面板的高度改为150px

:root { color-scheme: light dark; } html, body { margin: 0; padding: 0; } html { box-sizing: border-box; border: 1px solid red; height: 100vh; display: grid; > body { border: 5px solid green; margin: 1em; > div { height: 100px; border: 5px solid blue; } } }

Auto-fit in Maximized Viewport

This is a paragraph.

最外层视口的高度变小了,而body的最小高度大于视口高度。故绿色边框将直接突破红色边框的束缚。

在这种情况下,我们需要将bodymin-height属性值设置为0px

:root { color-scheme: light dark; } html, body { margin: 0; padding: 0; } html { box-sizing: border-box; border: 1px solid red; height: 100vh; display: grid; > body { min-height: 0; border: 5px solid green; margin: 1em; > div { height: 100px; border: 5px solid blue; } } }

Auto-fit in Maximized Viewport

This is a paragraph.

绿色边框不再受其子元素内容的束缚,从而重新跟随红色边框。

现在,红色边框与绿色边框均已经完全在视口范围内,但蓝色边框仍突破了这两个边框的界限。造成此的原因是,htmloverflow的默认值为auto,因而允许蓝色边框在html基础上所建立起的scroll container滚动容器)内可见。解决方法是,不在html上建立滚动容器,而应在body上建立。

:root { color-scheme: light dark; } html, body { margin: 0; padding: 0; } html { box-sizing: border-box; border: 1px solid red; height: 100vh; display: grid; overflow: hidden; > body { min-height: 0; overflow: scroll; border: 5px solid green; margin: 1em; > div { height: 100px; border: 5px solid blue; } } }

Auto-fit in Maximized Viewport

This is a paragraph.

将视口高度重新改为300px

:root { color-scheme: light dark; } html, body { margin: 0; padding: 0; } html { box-sizing: border-box; border: 1px solid red; height: 100vh; display: grid; overflow: hidden; > body { min-height: 0; overflow: scroll; border: 5px solid green; margin: 1em; > div { height: 100px; border: 5px solid blue; } } }

Auto-fit in Maximized Viewport

This is a paragraph.

红、绿、蓝这3个边框均按我们的期待而呈现出来。

此为独立运行的范例。运行之后,打开浏览器检查器,并随意调节检查器的高度,可看到无论其如何变化,红色、绿色的下边框均能紧贴着视口的下边界。

Flex

html, body { margin: 0; padding: 0; } html { box-sizing: border-box; border: 1px solid red; height: 100vh; display: flex; flex-direction: column; } body { flex: 1; border: 1px solid green; margin: 1em; } h1 { color: mediumaquamarine; border: 1px solid gray; }

Auto Fit in Maximized Viewport

Some texts.

Some texts.

Some texts.

输出面板的高度已被设置为固定的300px

根元素html设置为flex后,其唯一的子元素body的高度被设置为自动占满整个flex容器的空间。因此,当body内容比较少时,绿色边框也能铺满整个视口。

但是,当body的内容增加到10个段落文本时,绿色方框随之扩展,而超出了红色方框所代表的视口范围。

html, body { margin: 0; padding: 0; } html { box-sizing: border-box; border: 1px solid red; height: 100vh; display: flex; flex-direction: column; } body { flex: 1; border: 1px solid green; margin: 1em; } h1 { color: mediumaquamarine; border: 1px solid gray; }

Auto Fit in Maximized Viewport

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

问题是绿色方框超出了红色方框,且绿色方框内没有出现滚动条。

以下使用flexmin-height来解决问题:

html, body { margin: 0; padding: 0; } html { box-sizing: border-box; border: 1px solid red; height: 100vh; display: flex; flex-direction: column; } body { border: 1px solid green; margin: 1em; flex: 1; display: flex; flex-direction: column; min-height: 0; } div { border: 1px solid gray; flex: 1; overflow: scroll; } h1 { color: mediumaquamarine; border: 1px solid gray; }

Auto Fit in Maximized Viewport

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

flex子元素的min-height属性值默认为auto,导致body拒绝受到父容器高度的约束,从而继续撑开浏览器客户端下面的空间。将min-height的值设置为0,则body的高度值可以受父容器高度的约束。

推而广之,将上面的技术应用于多级嵌套的子元素中:

html, body { margin: 0; padding: 0; } html { box-sizing: border-box; border: 1px solid red; height: 100vh; display: flex; flex-direction: column; } body { border: 1px solid green; margin: 1em; flex: 1; display: flex; flex-direction: column; min-height: 0; } main { flex: 1; display: flex; flex-direction: column; min-height: 0; } div { border: 1px solid gray; flex: 1; overflow: scroll; } h1 { color: mediumaquamarine; border: 1px solid gray; }

Auto Fit in Maximized Viewport

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

Some texts.

此为独立运行的范例

参考资源

  1. CSS Backgrounds and Borders Module Level 3