接连两次面试被问到水平、垂直居中,答了几种方法,但感觉面试官并不是很满意啊,特意再整理一下各种方法~
该元素宽高已知
1. absolute+负margin
父元素:relative
该元素:absolute, left: 50%, top: 50%, margin-left: 负的该元素宽度的一半,margin-right: 负的该元素高度的一半
<!DOCTYPE HTML>
<html>
<head>
<title></title>
<meta http-equiv="content" content="text/html" charset="utf-8">
</head>
<body>
<style>
.div1 {
width: 100%;
height: 200px;
background-color: gray;
position:relative;
}
.div2 {
width:50px;
height:50px;
background-color:red;
position:absolute;
left:50%;
top:50%;
margin-left:-25px;
margin-top:-25px;
}
</style>
<div class="div1">
<div class="div2">A</div>
</div>
</body>
</html>
2. 绝对定位居中技术(Absolute Centering)absolute, margin:auto
这种方法的原理参见:绝对定位居中技术(Absolute Centering)
父元素设置为:relative
该元素设置为: absolute, left:0, top: 0, right:0,bottom:0, marign:auto
<!DOCTYPE HTML>
<html>
<head>
<title></title>
<meta http-equiv="content" content="text/html" charset="utf-8">
</head>
<body>
<style>
.div1 {
width: 100%;
height: 200px;
background-color: gray;
position:relative;
}
.div2 {
width:50px;
height:50px;
background-color:red;
margin:auto;
position:absolute;
left:0;
top:0;
right:0;
bottom:0;
}
</style>
<div class="div1">
<div class="div2">A</div>
</div>
</body>
</html>
3. flex布局
父元素:display:flex, justify-content: center, align-items: center
<!DOCTYPE HTML>
<html>
<head>
<title></title>
<meta http-equiv="content" content="text/html" charset="utf-8">
</head>
<body>
<style>
.div1 {
display:flex;
width: 100%;
height: 200px;
background-color: gray;
/* flex-direction:row; */
justify-content:center;
align-items:center;
}
.div2 {
/* flex: 0 1 auto; */
width:50px;
height:50px;
background-color:red;
}
</style>
<div class="div1">
<div class="div2">A</div>
</div>
</body>
</html>
该元素宽高未知
1. absolute, transform
父元素相对定位
子元素绝对定位,把定宽的负margin换成transform
<!DOCTYPE HTML>
<html>
<head>
<title></title>
<meta http-equiv="content" content="text/html" charset="utf-8">
</head>
<body>
<style>
.div1 {
position:relative;
width: 100%;
height: 200px;
background-color: gray;
}
.div2 {
position: absolute;
background-color:red;
left: 50%;
top: 50%;
transform: translate(-50%, -50%)
}
</style>
<div class="div1">
<div class="div2">Abfkadf;</div>
</div>
</body>
</html>
2.flex布局
<!DOCTYPE HTML>
<html>
<head>
<title></title>
<meta http-equiv="content" content="text/html" charset="utf-8">
</head>
<body>
<style>
.div1 {
display: flex;
width: 100%;
height: 200px;
background-color: gray;
justify-content: center;
align-items: center;
}
.div2 {
/* position: absolute; */
background-color:red;
}
</style>
<div class="div1">
<div class="div2">hhhhhh;</div>
</div>
</body>
</html>
其他
table-cell
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Demo001_displayTable</title>
<style>
/*** table-cell middle center组合使用 ***/
.cell {
display: table-cell;
vertical-align: middle;
text-align: center;
width: 240px;
height: 180px;
border: 1px solid #666;
}
</style>
</head>
<body>
<div class="cell">
<p>我爱你</p>
</div>
<div class="cell">
<p>我爱你</p>
<p>亲爱的中国</p>
</div>
<div class="cell">
<p>我爱你</p>
<p>亲爱的中国</p>
<div style="width:100px;height:50px;border:1px solid #ccc;display:inline-block">div(inline-block)</div>
</div>
</body>
</html>
inline-block 1
- 首先要了解垂直方向的对齐排版需使用 vertical-align,并且只应用于inline level, inline-block level 及 table-cells 元素上;
- 其次 vertical-align 的对齐就基于每个 line box(行框) 的,简单的说,inline level元素按照 Normal flow 水平排版出一行就会形成一个line box,其高度由内容形成,如果换行,则又是另一个line box,所有一段文本可能会分布在多个line box里,这些不重叠的line box被称作为a vertical stack of line boxes(一个垂直堆叠的线框集合)这些。
- 换句话说,我们的垂直居中是要在每个line box中进行处理。而上例中我们想让一行文本在名叫demo的高100px的容器里垂直居中,这时有个问题就是demo容器并非该行文本的line box,所以就算定义vertical-laign为middle也无法让该行文本在demo容器中垂直居中。我们知道line box的高度是由内容形成的,这时我们可以额外创建一个与该行文本处于同一line box的元素,同时将新增元素的高度定义为与demo容器相同,此时line box的高度将与demo一致,文本将会在line box内垂直居中,即同样实现了在demo容器中垂直居中。本例我们使用伪对象::after来创建那个新增元素,可以设置新增元素为不可见。
当然,该方案也是有局限性的,因为IE8以下的浏览器不支持伪对象::after
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Demo001_displayTable</title>
<style>
#demo {
height: 100px;
text-align: center;
}
#demo:after {
display: inline-block;
width: 0;
height: 100%;
vertical-align: middle;
content: '';
}
#demo p {
display: inline-block;
vertical-align: middle;
}
</style>
</head>
<body>
<div id="demo">
<p>水平垂直居中的随意内容</p>
</div>
</body>
</html>
inline-block 2
- 其实如果理解了line box概念,写上述2个例子时,就肯定知道会存在这个杯具。如上,CSS不变,只将文本变长。之前得以实现垂直居中,主要是将文本所在line box撑高了,而如果新增的元素被过长文本挤换行,则它们将不再处于同一line box,那么垂直居中将失效。你可能存疑,不是已将新增元素width设置为0了吗?怎么还能被挤换行。这时你应该知道一个常识,inline level或inline-block level的元素之间的间隙问题,对此问题不做详述。
以下是终极版,包含浏览器兼容,过长问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Demo001_displayTable</title>
<style>
#demo {
height: 100px;
text-align: center;
font-size: 0;
}
#demo:after,
#demo span {
display: inline-block;
*display: inline;
*zoom: 1;
width: 0;
height: 100%;
vertical-align: middle;
}
#demo:after {
content: '';
}
#demo p {
display: inline-block;
*display: inline;
*zoom: 1;
vertical-align: middle;
font-size: 16px;
}
</style>
</head>
<body>
<div id="demo">
<p>这是一个终极实现的水平垂直居中实例</p>
<!--[if lt IE 8]><span></span><![endif]-->
</div>
</body>
</html>