CSS 垂直居中
欢迎大家先来看看我的水平居中篇:http://www.cnblogs.com/cuncunjun/p/6549955.html
首先要清楚一个问题,什么时候你会要设置垂直居中?大家不要被各种例子弄晕头,静下心来想一想!
• 一个父元素,如果不设置高度的话,默认就是紧包着子元素,如果你的 padding-top 和 padding-bottom 是相等,那么这本身就是一个垂直居中的效果!!!!!
• 当然,如果你的子元素并不独占一行,而是行内元素和 inline-block 元素的话就不一样了。比如下面这个例子:
<div id="container">
<span>aaaaaaaaaaaa我我我</span>
<img src="1.jpg" width="100px"/><img src="1.jpg" width="120px"/>
</div>

这涉及到一个知识点,就是line-box原理。详情可见张鑫旭老师的博客: http://www.zhangxinxu.com/wordpress/2010/01/css-float 浮动的深入研究、详解及拓展一 /

inline 和 inline-block 都是在一行显示,如图所示由于图片本身有高度,就会把整个行高撑大,但是文字和图片依然在一行。
相信细心地朋友会发现,图片下面有一条小空白。这就涉及到了 vertical-align 属性,张鑫旭老师的博客写的很详细。在这里我给大家简单总结一下。
vertical-align 只对 inline-block 元素有效,换句话,inline-block 自带 vertical-align 属性。属性的值有很多,主要有下图这几种:

Vertical-align 默认值是 baseline!即使你没有设置这个属性,也会有。所以图片是和整个 line-box 的 baseline 对齐,所以下面会有空白。
言归正传:这种情况下,谁想居中谁就自己设 Vertical-align:middle;当然只对 line-block 有效!比如我对两个图片设置垂直居中,
#container{
border:2px solid blue;
}
img{
vertical-align:middle ;
}

效果如图所示,很多人可能会问,怎么文字也居中了呢?
答:其实不是文字居中,而是图片相对整个行居中,也就是文字所在的行居中,图片下移,这个时候上方被图片撑起来的 line-height 变矮了,所以整个行都上移,直到最高的图片碰到父元素的 border。只不过视觉效果上是文字也居中了。
• 再然后,就是父元素设置了 height,子元素如何垂直居中?
记住一点 vertical-heigh 只是针对 inline-block 有效,并且仅仅是相对元素所在 line-box 垂直居中!!也就是说只能在一行中折腾!
#container{
border:2px solid blue;
height:250px;
}
img{
display:inline-block;
vertical-align:middle ;
}

我给父元素设置了高度,会发现图片仍然只在自己的那行居中,并不在整个父元素居中。
就算是块状元素设置 display:inline-block,也是只在自己那一行居中!
所以这种情况,vertical-align 就排不上用场了,当然还是有居中的办法,具体见下文喽!!
1.line-height(适用单行文本 )##
height: 该元素的高度,line-height: 指在文本中,行与行之间的 基线间的距离 。 设置 line-height,比 font-size 大就行了。height 不设就行,默认是 line-height 的高,非得设值的话,就 height=line-height 即可。 ```
##2. 适用于父元素有自己的的 height,自己是块状元素的情况(最常用)##
**a. 负外边距: 设置元素为 absolute/relative/fixed,(1)偏移量(top 或者 bottom)设置为 50%,(2)margin 设置为元素宽度一半乘以 -1。** 如果块元素尺寸已知,可以通过以下方式让内容块居中于容器显示: 通过 absolute 设置 top: 50%; left: 50%; 外边距 margin 取负数,大小为 width/height(不使用 box-sizing: border-box 时包括 padding)的一半。 ```
b. position:absolute/fixed + top,bottom:0 + margin:auto
<div id="a">
<div id="b"> 看我是否可以居中。</div>
</div>
#a{
border: solid blue;
width:800px;
height:350px;
margin:50px;
padding:40px;
position: relative;
}
#b {
width: 300px;
height: 100px;
padding: 20px;
border: 1px solid red;
position:absolute;
top:0;
bottom: 0;
margin:auto 0;
}
和水平居中是一个原理,如果被居中的元素没有设置 height 的话,content 就会被扯大,充满父元素。
position:relative 就失效了,因为他和父元素没有关系而是相对原来的位置偏移,上下设置 top bottom:0 是没有变化的。
fixed 可以实现居中,只不过不是相对父元素而是可视窗口。
3. 父元素 height 随意,自己是行内、块状都适用 ###
- **a. table 标签 ** 使用插入 table(包括 tbody、tr、td) 标签 ```
<div class="table-wrapper"><table><tbody><tr><td class="wrap">
<div>
<div>看我是否可以居中。</div>
<div>看我是否可以居中。</div>
<div>看我是否可以居中。</div>
</div>
</td></tr></tbody></table></div>
css 代码:
table td{height:300px;background:#ccc;padding:0;}
<img src="//upload-images.jianshu.io/upload_images/5146771-ac2d318b61153524.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="Paste_Image.png" loading="lazy"><br>
因为 td 标签默认情况下就默认设置了 vertical-align 为 middle,所以我们不需要显式地设置了。虽然我显示设值了padding为0,但是根据图片来看,td的content是紧包着子元素的,剩下的用padding来填充,所以视觉上是垂直居中的效果。无论里面包含的是文本还是图片。
<ul>
<li><strong>b. display:table-cell + vertical-align:middle</strong><br>
在 chrome、firefox 及 IE8 以上的浏览器下可以设置块级元素的display 为 table-cell(设置为表格单元显示),激活 vertical-align 属性,但注意 IE6、7 并不支持这个样式, 兼容性比较差。注意和新增table标签不一样的是一定要设置vertical-align。<strong>(给父亲设不是给自己)</strong></li>
</ul>
<pre class="highlighter-hljs" highlighted="true"><code class="highlighter-hljs hljs language-xml"><span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">p</span>></span>看我是否可以居中。<span class="hljs-tag"></<span class="hljs-name">p</span>></span>
<span class="hljs-tag"><<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">""</span>/></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"><<span class="hljs-name">style</span>></span><span class="language-css">
<span class="hljs-selector-class">.container</span>{
<span class="hljs-attribute">height</span>:<span class="hljs-number">300px</span>;
<span class="hljs-attribute">background</span>:<span class="hljs-number">#ccc</span>;
<span class="hljs-attribute">display</span>:table-cell;<span class="hljs-comment">/*IE8以上及Chrome、Firefox*/</span>
<span class="hljs-attribute">vertical-align</span>:middle;<span class="hljs-comment">/*IE8以上及Chrome、Firefox*/</span>
}
</span><span class="hljs-tag"></<span class="hljs-name">style</span>></span>
</code></pre>
<img src="//upload-images.jianshu.io/upload_images/5146771-148aac11e3bc17d1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="Paste_Image.png" loading="lazy">
<hr>
感谢评论区的朋友,提供了一种新的思路。但是有一点错误,我后面会指正出来,不管怎么还是谢谢你!
前面提到的都是css的传统布局方法,垂直居中实现起来确实什么麻烦。2009年,W3C提出了一种新的方案—-**Flex布局**,可以简便、完整、响应式地实现各种页面布局。目前,它已经得到了所有浏览器的支持,这意味着,现在就能很安全地使用这项功能。
关于flex布局的基础知识我就不一一列举了,菜鸟教程这一节讲的什么清晰,大家可以自行学习。http://www.runoob.com/w3cnote/flex-grammar.html
<hr>
<br>
##4.CSS3的flex弹性盒子布局法##
让我带着大家来逐步尝试,首先给父元素设置display:flex,并设置按照主轴的排列方式即水平方向从左到右依次排列row,如果你想要垂直居中的子元素只有一行可以设置nowrap。如果你想要好几行元素作为整体一起居中的话就可以设置wrap。flex布局真的很神奇很方便!
#container{
width:600px;
border:2px solid blue;
display:flex;
flex-flow: row nowrap;
}





那我们给图片分别设置好高度之后,接下来,就要真正的设置垂直居中了!
注意 justify-content:center; 是水平居中。而垂直居中是 align-items:center;
附上完整代码:
#container{
width:600px;
border:2px solid blue;
height:250px;
display:flex;
flex-flow: row nowrap;
align-items:center;
}
<div id="container">
<span id="child">aaaaaaaaaaaa我我我</span>
<img src="1.jpg" width="100px" height="100px"/>
<img src="1.jpg" width="120px" height="120px"/>
<img src="1.jpg" width="80px" height="80px"/>
<img src="1.jpg" width="110px" height="110px"/>
</div>

完美!!!
有同学可能会产生疑问,如果子元素是块状元素怎么办?
flex 布局很强大,无论子元素是块状还是行内统统都排排坐在一行,谁也不能独占一行。进了 flex 的门,一生都是 flex 的魂!!!
flex 还有很多其他好玩的属性,大家可以自己去练练手,十分有趣!!