从项目需求角度,使用纯CSS方案解决垂直居中
CSS是HTML元素的剪刀手,它极度的丰富了web页面的修饰。在众多CSS常见的样式需求中,有一奇葩式的存在【垂直居中】,因为不管是从逻辑实现方面还是从正常需求量来讲,这都没理由让这个需求在实践过程中,显的那么艰难。我们往往需要额外添加标签元素与充满hack味道的属性才能解决,而在涉及到不固定元素尺寸的时候,更显艰难。唉,日子还得照样过,工作还得继续干,这里就从实际需求的角度来归纳一些纯CSS方案。【特别说明,现实中的需求千变万化,请阅者根据实际需求】
文本内容的垂直居中这是一个烂大街的需求,比如在页面中某一块内容的标题上和单行列表上就会有用到。如下图:
现在我们就假设需要在一个宽400px,高32px的div上,使里面的一行文字垂直居中,主要效果如下图:
实现上面需求的HTML代码如下:
<div class="box"><span>标题标题</span></div>
CSS实现的代码如下:
.box{ width: 400px; background-color: #ccc; color: #333; line-height:32px; /*主要实现代码*/ }
实现上面的需求,我们还可以用内填充来解决。不过用这个方法得事先了解我们事先的css reset或者浏览器对页面设置的默认行高是多少。假设为24px,那么我们把32px高度减去默认行高的24px,然后除以2得到4px,然后用内填充填上,所以我们可以改成这样:
.box{ width: 400px; background-color: #ccc; color: #333; padding: 4px 0; /*主要实现代码*/ }
这样麻烦是麻烦了点,但总解决了问题。
需求是永无止境的,上面是实现了单行的文本问题,如果我们要实现多行文本的内容的垂直居中该怎么办呢?如下图,一个宽400px,高300px的div:
上面实现的HTML代码如下:
<div class="box"> <p>标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题</p> </div>
你肯定想到了用内填充来解决这个问题,毕竟是固定高度的(代码就不附上了),可是如果我们里面的内容再多增加一行,或者减去一行,这种方法就行不通了。这时,我们就可以利用table的特性来解决;
.box{ height:300px; width: 400px; background-color: #ccc; color: #333; display: table; /*设置父标签为table展示*/ } .box > p{ display: table-cell;/*设置子标签为表格的单元格*/ vertical-align: middle;/*设置子标签单元格展现内容方式*/ }
这种方法是在IE7以及以下是没有用的,因为它们不支持标签转变为table的变化,即 display: table; 与display: table-cell;当然你可以直接用表格布局,这无所谓。好在聪明人很多,我们前端的前辈们研究了另外一种方法来实现上述内容,但html结构有变化,具体如下:
<!--html代码--> <div class="box"> <div> <div><p>标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题</p></div> </div> </div> <!--css代码--> <style> .box{ width: 400px; height: 300px; position: relative; background-color: #ccc; color: #333; } .box > div{ position: absolute; top: 50%; left: 0; } .box > div > div{ position: relative; top: -50%; left: 0; } </style>
这只适用IE7及以下,随着浏览器的不断升级,我们可能不需要兼容这么低版本的浏览器,当做一种了解吧。
像上面的利用table的特性来布局,里面的内容是包括div和图片的。这个可以自己试试,放入固定高宽的块级元素和图片。(注意一点,p标签里面放入div,在一些浏览器中实际显示中会把p标签分割成两个,所以你可以把子元素改成div)
而如果单单你只想图片的垂直居中,你可以使用如下的方式:
<!--html代码--> <div class="box1"> <img src="xxxxx.png"> </div> <!--css代码--> <style> .box1{ background-color: #ccc; line-height: 300px; width: 400px; } .box1 > img{vertical-align: middle;} </style>
具体效果自己看吧。
以上都是文本内容的垂直居中,但是我们平时工作中用的多的还有另外一种情况,即盒子居中,即div居中。如下图,下图是一个div,宽400px,高300px:
聪明如你,一定会用到了table来解决。这也是一种解决方案,我们还可以用定位来解决方法,如:
.box{ height:300px; width: 400px; background-color: #ccc; color: #333; position: absolute;/*这里也可以使用fixed,看自己情况而定*/ top: 50%; left: 50%; margin:-150px 0 0 -200px; }
或者你也可以使用下面的代码
/*代码不适用与IE7及以下*/
.box{ height:300px; width:400px; background-color: #ccc; color: #333; position: fixed;/*这里也可以使用fixed,看自己情况而定*/ top:0; left:0; bottom:0; right:0; margin:auto; }
以上方法都需要一个固定的高度的,如果们不确定内容的高度该怎么实现呢?利用上面的table是可以办到的,如果你的项目不用兼容不支持CSS3的浏览器话,可以试试以下的方法:
.box{ width:200px; background-color: #ccc; color: #333; position: fixed;/*可以切换为absolute*/ top: 50%; left: 50%; transform: translate(-50%, -50%); }
既然你的项目这么超前,我们也可以使用flexbox(伸缩盒)来布局,使用这种方法我们是可以不用指定宽度的,,代码如下:
body { display: flex; min-height: 100vh; margin: 0; } .box { background-color: #ccc; margin: auto 20px; }
总结:这么多的方法都不是那么完美的,具体情况具体而定吧,据说CSS发展到未来,会直接用一个属性align-self: center;来搞定所有元素的垂直居中,期待那天的到来吧。