第 52 题:怎么让一个 div 水平垂直居中
zeroone001 opened this issue · 26 comments
<div class="parent">
<div class="child"></div>
</div>
div.parent {
display: flex;
justify-content: center;
align-items: center;
}
div.parent {
position: relative;
}
div.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/* 或者 */
div.child {
width: 50px;
height: 10px;
position: absolute;
top: 50%;
left: 50%;
margin-left: -25px;
margin-top: -5px;
}
/* 或 */
div.child {
width: 50px;
height: 10px;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
}
div.parent {
display: grid;
}
div.child {
justify-self: center;
align-self: center;
}
div.parent {
font-size: 0;
text-align: center;
&::before {
content: "";
display: inline-block;
width: 0;
height: 100%;
vertical-align: middle;
}
}
div.child{
display: inline-block;
vertical-align: middle;
}
楼上总结的差不多了。再加一种
div.parent{
display:flex;
}
div.child{
margin:auto;
}
div.parent {
display: table;
}
div.child {
display: table-cell
vertical-align: middle;
text-align: center;
}
补充一个,使用 table-cell 的方式:
.parent {
display: table-cell;
height: 200px;
width: 200px;
background-color: orange;
text-align: center;
vertical-align: middle;
}
.child {
display: inline-block;
width: 100px;
height: 100px;
background-color: blue;
}
<div class="parent">
<div class="child"></div>
</div>
水平垂直居中有好多种实现方式,主要就分为两类不定宽高和定宽高
以在body下插入一个div为例
- 定宽高
使用定位+margin
element.style {
position: absolute;
left: 50%;
top: 50%;
margin-left: -250px;
margin-top: -250px;
width: 500px;
height: 500px;
background: yellow;
z-index: 1;
}
使用定位+transfrom
element.style {
position: absolute;
left: 50%;
top: 50%;
width: 500px;
height: 500px;
background: yellow;
z-index: 1;
transform: translate3d(-50%,-50%,0);
}
- 不定宽高
不定宽高的方法基本都适用于定宽高的情况
这里把div的宽高按照内容展开
使用定位+transform同样是适用的
element.style {
position: absolute;
left: 50%;
top: 50%;
background: yellow;
z-index: 1;
transform: translate3d(-50%,-50%,0);
}
还有一些其他的方法比如使用父容器使用flex,grid,table
这两个楼上也提到了,是可以实现的,但是在实际应用中,
因为改变了父容器的display,在多个子节点反而不好用了
楼上总结的差不多了。再加一种
div.parent{ display:flex; } div.child{ margin:auto; }
同理:
div.parent{ display:grid; } div.child{ margin:auto; }
div.parent {
display: table;
}
div.child {
display: table-cell
vertical-align: middle;
text-align: center;
}
需要再补充一个@cleverboy32
div.grandson {
display:inline-block;
width: 10px;
height: 10px;
}
<div class="parent"><div class="child"><div class="grandson"></div></div></div>
1.
div.parent {
display:flex;
justify-content:center;
align-items:center;
}
2.
div.parent {
position:relative;
}
div.child{
position:absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%);
}
补充一个,使用 table-cell 的方式:
.parent { display: table-cell; height: 200px; width: 200px; background-color: orange; text-align: center; vertical-align: middle; } .child { display: inline-block; width: 100px; height: 100px; background-color: blue; }<div class="parent"> <div class="child"></div> </div>
table-cell 是不支持设置 width: 100%; 想让 .parent
和 其容器宽度一致最好设置一个 dispaly: table;
父容器。
<div class="parent-fix">
<div class="parent">
<div class="child">DEMO</div>
</div>
</div>
.parent-fix {
display: table;
width: 100%;
}
.parent {
display: table-cell;
text-align: center;
vertical-align: middle;
height: 200px;
background-color: #ccc;
}
.child {
display: inline-block;
background-color: #000;
line-height: 50px;
color: #fff;
}
@zeroone001 在 parent 有宽高的时候, child 已经垂直居中了
@zeroone001 在 parent 有宽高的时候, child 已经垂直居中了
不行
display: table-cell; 这个居中不了,必须要第三个元素在child里面
<div class="box">
<div class="center">
</div>
.box {
width: 500px;
height: 500px;
text-align: center; /*center*/
}
.box::after {
content: '';
display: inline-block;
width: 0;
height: 100%;
vertical-align: middle;
}
.center {
display: inline-block;
width: 100px;
height: 100px;
vertical-align: middle;/*center*/
}
// 1. line-height + text-algin
.parent {
height: 100px;
line-height: 100px;
text-align: center;
}
.child {
}
// 2. text-align + vertail-align
.parent {
text-align: center;
}
.child {
display: inline-block;
vertical-align: middle;
}
// 3. table-cell + vertail-align
.parent {
display: table-cell;
vertical-align: middle;
}
.child {
}
// 4. position + margin
.parent {
position: relative;
}
.child {
width: 100px;
height: 100px;
position: absolute;
left: calc(50% - 50px);
top: calc(50% - 50px);
}
// 5.position + transform
.parent {
position: relative;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
// 6. flex
.parent {
display: flex;
}
.child {
align-items: center;
justify-content: center;
}
楼上大神们指出的很全了,
我指出一点:
使用 margin-left 和 margin-top, 相对的是父元素,
transform: translate 相对的自身,
这是他们的一点区别,实际上我是想问一下,他们还有没有其他的区别 ,望后续大神指出;
前端小白,有错勿怪,感谢指正
// 1. line-height + text-algin .parent { height: 100px; line-height: 100px; text-align: center; } .child { } // 2. text-align + vertail-align .parent { text-align: center; } .child { display: inline-block; vertical-align: middle; } // 3. table-cell + vertail-align .parent { display: table-cell; vertical-align: middle; } .child { } // 4. position + margin .parent { position: relative; } .child { width: 100px; height: 100px; position: absolute; left: calc(50% - 50px); top: calc(50% - 50px); } // 5.position + transform .parent { position: relative; } .child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } // 6. flex .parent { display: flex; } .child { align-items: center; justify-content: center; }
方法2 只能水平居中,方法3导致div.parent宽度和div.parent宽度一样,且设置width样式无效
div.parent { display: table; } div.child { display: table-cell vertical-align: middle; text-align: center; }
这个设置table-cell 的盒子会占满父盒子,里面的文字才能居中。
div.parent { font-size: 0; text-align: center; &::before { content: ""; display: inline-block; width: 0; height: 100%; vertical-align: middle; } } div.child{ display: inline-block; vertical-align: middle; }
能说一下这种实现方式的原理吗
div.parent { font-size: 0; text-align: center; &::before { content: ""; display: inline-block; width: 0; height: 100%; vertical-align: middle; } } div.child{ display: inline-block; vertical-align: middle; }能说一下这种实现方式的原理吗
这个我前几天刚在张鑫旭的《CSS世界》里面第一次看到,原理就是(基于我个人的理解):设置inline-block和vertical-align:middle后,里面的元素会基于中间的文字准线居中对齐(学生时代的英语本子里面写字母,都是4条线形成三个空白区域,文字的对齐就是根据这几条线的)vertical-align更多信息可以看看张鑫旭博文;
然后,由于伪类是position:static(默认)的,那么伪类撑开了父元素的基准线(高度是100%),使得此时文字的基准线就是整个div.parent的中心了,另外vertical-align只影响inline或者inline-block的,所以div.child设置vertical-align就能居中了。
以上是我个人的理解,有很多表达不清楚的地方,更详细的内容还是推荐张鑫旭的博文。
可以用calc来计算,这样代码少一点
.parent {
border: 1px solid;
width: 1000px;
height: 1000px;
}
.child {
position: relative;
border: 1px solid;
width: 100px;
height: 100px;
top: calc(50% - 50px);
left: calc(50% - 50px);
}
<div class="parent"> <div class="child"></div> </div>
div.parent { display: flex; justify-content: center; align-items: center; }div.parent { position: relative; } div.child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } /* 或者 */ div.child { width: 50px; height: 10px; position: absolute; top: 50%; left: 50%; margin-left: -25px; margin-top: -5px; } /* 或 */ div.child { width: 50px; height: 10px; position: absolute; left: 0; top: 0; right: 0; bottom: 0; margin: auto; }div.parent { display: grid; } div.child { justify-self: center; align-self: center; }div.parent { font-size: 0; text-align: center; &::before { content: ""; display: inline-block; width: 0; height: 100%; vertical-align: middle; } } div.child{ display: inline-block; vertical-align: middle; }
提个建议,可以在每一种实现上写一下**和场景
楼上大神们指出的很全了,
我指出一点:
使用 margin-left 和 margin-top, 相对的是父元素,
transform: translate 相对的自身,
这是他们的一点区别,实际上我是想问一下,他们还有没有其他的区别 ,望后续大神指出;前端小白,有错勿怪,感谢指正
margin是给自己加个外边框,是相对自身原来的位置来变化吧
学无止境~
div.parent {
position: relative;
}
div.child {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
div.parent{
display:grid;
place-items: center;
}
div.parent { font-size: 0; text-align: center; &::before { content: ""; display: inline-block; width: 0; height: 100%; vertical-align: middle; } } div.child{ display: inline-block; vertical-align: middle; }能说一下这种实现方式的原理吗
在73题的IFC中有人提到了IFC的应用场景:垂直居中项应该就是这种方式的实现原理
1、使用绝对定位
<div
style={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
backgroundColor: "seagreen"
}}
>
居中元素
</div>
2、不使用绝对定位,使用flex
<div
style={{
display: "flex",
width: 300,
height: 300,
margin: "20px auto",
border: "2px solid #333"
}}
>
<div
style={{
width: 40,
height: 40,
margin: "auto",
backgroundColor: "seagreen"
}}
>
居中元素
</div>
</div>
3、使用table-cell,display为table-cell同时使用verticalAlign: middle会让元素垂直居中
<div
style={{
display: "table-cell",
verticalAlign: "middle",
width: 300,
height: 300,
margin: "20px auto",
border: "2px solid #333"
}}
>
<div
style={{
width: 40,
height: 60,
display: "inline-block",
backgroundColor: "seagreen"
}}
>
居中元素
</div>
</div>