认为自己的 CSS 停留在会用的阶段,遇到复杂一些的效果都是各种尝试,没有一些理性的知识做支撑。
这次离职闲暇之余,便想着整理一下常见的 CSS 问题,下次遇到相应的场景,也能够有些参考。
利用 text-align: center 可以实现 块级元素内部 的 内联元素 水平居中
文本
<p style="text-align: center;background: #f06d06;">
我要居中
</p>
display 值为 inline, inline-block, inline-table, inline-flex 之一
<p style="text-align: center;background: #f06d06;">
<div style="display: inline;">
我要居中
</div>
</p>
在测试以上代码的时候,发现并不能居中,而且最终渲染的结果是:
<p style="text-align: center;background: #f06d06;">
</p>
<div style="display: inline;">
我要居中
</div>
<p>
</p>
也就是说, p 标签中不能嵌套 div 标签,否则会造成这种 bug.
于是换用以下代码测试:
<div style="text-align: center;background: #f06d06;">
// 换成 inline-block, inlint-table, inline-flex 均可
<div style="display: inline-flex;background: white;">
我要居中
</div>
</div>
通过 margin:0 auto; 使得块级元素水平居中,前提是 设置了居中元素的 width
<div style="background: #f06d06;">
<div style="width: 200px;margin: 0 auto;background: white;">
我要居中
</div>
</div>
<div style="background: blue; position: relative;">
<div style="background: red; margin: 0 auto; width: fit-content;">
我要居中 我要居中 我要居中 我要居中
</div>
</div>
同上,使用 margin:0 auto; 设置要居中元素为 width: fit-content (相当于明确设置居中元素的宽度), 在 实现水平居中。
缺点是, fit-content 的浏览器兼容略差
通过设置要居中的元素向右移动父元素的 50%, 再向左移动自身元素的 -50%, 即可试下居中。
<div style="background: blue; position: relative;">
<div style="position: absolute; left: 50%; transform: translateX(-50%); background: red;">
我要居中 我要居中 我要居中 我要居中
</div>
</div>
如果已知子元素宽度,比如:
<div style="background: blue; position: relative;">
<div style="position: absolute; width: 400px; left: 50%; transform: translateX(-50%); background: red;">
我要居中 我要居中 我要居中 我要居中
</div>
</div>
此时 tranxlateX(-50%) 还可以换成 margin-left: -200px.
另外,还可以利用 calc, 设置准确的 left 值:
<div style="background: blue; position: relative;">
<div style="position: absolute; width: 400px; left: calc(50% - 200px); background: red;">
我要居中 我要居中 我要居中 我要居中
</div>
</div>
即通过让块级元素变为 inline-block 元素,再让父级 text-align: center 使得元素居中
<div style="text-align: center;">
<div style="background: red; display: inline-block;">
a
</div>
<div style="background: red; display: inline-block;">
b
</div>
<div style="background: red; display: inline-block;">
c
</div>
</div>
通过父元素设置为 flex 布局,并设置 justify-content: center 实现居中
<div style="display: flex; justify-content:center;">
<div style="background: red;">
a
</div>
<div style="background: red;">
b
</div>
<div style="background: red;">
c
</div>
</div>
原理是,设置多个元素的共同父元素 float:left, 那么父元素的宽度即为其内容(即子元素)的宽度。子元素设置为 float: left, 保证多个子元素都在同一行。
接着父元素 A 相对父元素的父元素 B left: 50%。然后子元素 C 设置 right: 50% 相对与 A的,其实就类似 A 元素 transform: translateX(-50%), 从而实现居中。
<div style="background: blue;">
<div style="float: left; position: relative; left: 50%;">
<div style="background: red;float: left;width: 200px;position: relative; right: 50%;">
a
</div>
<div style="background: red;float: left; width: 200px;position: relative; right: 50%;">
b
</div>
<div style="background: red;float: left; width: 200px;position: relative; right: 50%;">
c
</div>
</div>
</div>
原理同上,通过设置父元素为 position: absolute,使得父元素宽度取决于所包含的内容(即子元素)的宽度
<div style="background: blue;">
<div style="position: absolute; left: 50%;">
<div style="background: red;float: left;width: 200px;position: relative; right: 50%;">
a
</div>
<div style="background: red;float: left; width: 200px;position: relative; right: 50%;">
b
</div>
<div style="background: red;float: left; width: 200px;position: relative; right: 50%;">
c
</div>
</div>
</div>
即通过设置 padding-top 和 padding-bottom 相等,使得文字居中 (适用于单行和多行文字)
<div style="background: blue; padding: 20px 0;">
我要垂直居中
</div>
即设置 line-height 的值与height值一样,但只适用于单行文本,如果有多行,则无效。
<div style=" height: 40px;background: blue; line-height: 40px;">
我要垂直居中
</div>
支持多行文本垂直居中
设置父元素为 display: table,并设定高度。 子元素设为 display: table-cell; vertical-align: middle; 即可
<div style="display: table; height: 100px;">
<div style="background: blue; display: table-cell;vertical-align: middle;">
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
</div>
</div>
同理,我们也可以直接用 table 标签:
默认 tbody 的 vertivcal-align 即为 middle;
<table style="background: red; height: 200px;">
<tbody>
<tr>
<td>
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
</td>
</tr>
</tbody>
</table>
<div style="background: red; height: 200px; display: flex; flex-direction: column; justify-content: center;">
<div>
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
</div>
</div>
即某个元素需要垂直居中,那么可以给它加一个兄弟元素(通过父元素为元素的方式),其高度为父元素的 100%.
同时设置两个元素都是 inline-block, 再通过 vertical-align:middle 实现垂直居中。
<style>
.ghost-center:before {
content: " ";
display: inline-block;
height: 100%;
width: 1%;
vertical-align: middle;
}
</style>
<div style="background: red;height: 200px; position: relative;" class="ghost-center">
// 注意 p 标签必须限制宽度
<p style="display: inline-block;background: blue; vertical-align: middle; width: 200px;">
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
</p>
</div>
元素高度已知
<div style="background: red;height: 200px; position: relative;">
<p style="background: blue; position: absolute; top: 50%; margin-top: -50px; height: 100px;">
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
</p>
</div>
元素高度未知
同水平居中一样,高度未知时可以采用 transform: translateY(-50%) 的方式:
<div style="background: red;height: 200px; position: relative;">
<p style="margin: 0; background: blue; position: absolute; top: 50%; transform: translateY(-50%); height: 100px;">
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
</p>
</div>
<div style="display: flex; height: 300px; background: red; align-items: center;">
<div style="background: blue; height: 100px;">
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
</div>
</div>
同行内元素垂直居中(2.1.3部分内容):
<table>
<tbody>
<tr>
<td>
<div style="background: green;">
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
</div>
</td>
</tr>
</tbody>
</table>
display: table-cell 也是一样的:
<div style="display: table; height: 300px; background: red;">
<div style="display: table-cell;vertical-align: middle;">
<div style="background: blue;">
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中 我要垂直居中
</div>
</div>
</div>
元素宽高已知
<div style="height: 400px; width: 400px; background: red; position: relative;">
<div
style="background: blue; height: 100px; width: 100px; position: absolute; left: 50%; top: 50%; margin-left: -50px; margin-top: -50px;">
水平垂直居中
</div>
</div>
absolute + calc 的方式适用于元素宽高已知的情况
同理还有 transform 的方式适用于元素宽高未知的情况
略,同以上 flex 的方式
display: flex;
justify-content: center;
align-items: center;
即通过绝对定位,同时设置 left,right,top,bottom 均为 0, 此时再设置 margin: auto; 即可实现水平垂直居中。前提是已知元素的宽高
<div style="height: 400px; width: 400px; background: red; position: relative;">
<div
style="background: blue; height: 100px; width: 100px; position: absolute; left: 0; right: 0;top:0;bottom:0;margin: auto;">
水平垂直居中
</div>
</div>
即通过 line-height 垂直居中, text-align: center; 实现水平居中。
在子元素中, line-height: initial; text-align: left; 都是为了消除父元素样式对自己的影响。
<div style="line-height: 200px; width: 200px; background: blue; text-align: center;">
<div style="background: green; display: inline-block;line-height: initial; text-align: left;">
我要垂直居中
</div>
</div>
本文只是对于网上答案的整理,没有原创部分,仅用于自己备忘,在实际工作中遇到相关问题能有资料参考。

