关于多行文本的垂直居中问题
今天在修改老项目中样式的时候,遇到这个经典的居中问题。对于IE8+的浏览器,实现方式有很多(最便捷的一种是利用table布局),不再赘述,百度一大堆方法。
我今天遇到的情况是,需要设计一个底部导航栏(导航栏宽高固定),导航栏的item数是动态可变的,导航栏中的文字根据配置信息,拥有 9种可能的语言,针对一些文本长度较长的语言,可能涉及到 多行文本居中。而公司设备上是IE7,故记录一下对IE7/6兼容的多行文本垂直居中解决方法。
先上JSP代码>>>
<div id="guide_bottom">
<c:if test="${Print == '1'}">
<div class="guide_item" onclick="print()"><div class="guide_txt"><spring:message code='my.print'/></div></div>
</c:if>
<c:if test="${Query == '1'}">
<div class="guide_item" onclick="query()"><div class="guide_txt"><spring:message code='my.query'/></div></div>
</c:if>
<c:if test="${Join == '1'}">
<div class="guide_item" onclick="join()"><div class="guide_txt"><spring:message code='my.join'/></div></div>
</c:if>
<c:if test="${Change == '1'}">
<div class="guide_item" onclick="change()"><div class="guide_txt"><spring:message code='my.change'/></div></div>
</c:if>
<c:if test="${Cancel == '1'}">
<div class="guide_item" onclick="cancel()"><div class="guide_txt"><spring:message code='my.cancel'/></div></div>
</c:if>
</div>
用到的css如下>>>
#guide_bottom{
width:1024px;
height:55px;
position:absolute;
bottom:0;
left:0;
}
.guide_item{
width:200px;
height:55px;
box-sizing:border-box;
float:left;
cursor:pointer;
border:2px solid rgb(75,115,220);
border-width:0 2px 0 0;
}
.guide_txt{
/*宽高根据文字内容自适应*/
display:inline-block;
/*IE7不支持inline-block,下面兼容IE7*/
*display:inline;
*zoom:1;
max-width:97%; /*给两边留点间距,模拟padding*/
word-wrap:break-word;/*允许过长单词在一行中被截断*/
text-align:center; /*若换行,则下方文字水平居中*/
}
大概布局如上所示。
最开始我查了很多方法,其中有一种利用position:absolute;
然后分别设置top:50%;left:50%;
并通过设置margin-left:-20px; margin-top:-30px;
(假如子元素的宽高分别是40px、60px),那么能实现垂直水平居中。因为top:50%;left:50%;
实现的是子元素盒子的左上角坐标,恰好位于父元素的中心,再通过margin
向左、向上移动半个子元素的宽度和高度,则能使子元素盒子恰好位于父元素的中心。
然鹅,IE7并不买账,绝对定位设置top和left的百分比,并与margin结合会产生一些奇怪的现象,使得实际达不到居中的效果(我这里显示为子元素内的文字被截取,还未铺满第一行就开始换行)。
最后我用JS,在页面加载完后,实时计算盒模型的实际宽高,然后只通过设置margin-left; margin-top;
实现了垂直水平居中。听同事讲,在页面使用JS操作DOM,会影响响应速度,不过现在也管不了那么多了,先把样式问题解决,以后再来看优化问题吧。
以下是我的JS实现:
$(function(){
//IE7下不支持getElementsByClassName,故手动获取相关节点
var rootNode = document.getElementById("guide_bottom");
var allNodes = rootNode.getElementsByTagName("*");
for(var i = 0; i < allNodes.length; i++){
var item = allNodes[i];
if(item.nodeType == 1 && item.className == "guide_txt"){
var left = (item.parentNode.clientWidth - item.clientWidth)/2 + "px";
var top = (item.parentNode.clientHeight - item.clientHeight)/2 + "px";
//clientWidth 对象内容的可视区域宽度
item.style.marginLeft = left;
item.style.marginTop = top;
}
//至此,垂直居中实现
//导航栏条目预设宽度为200px,底部导航栏宽度为1024px,最多可容纳5个条目
//条目数目超过5个时,运用百分比方式动态设置width来实现调整,不为本篇重点,不再赘述
}
});
另:
IE7下对盒子模型的宽高的解析,与IE8+,chrome等有区别。例如:设置盒子的width:200px;
再给个左边框border-left:2px solid red;
(3个属性同时给出才会有效)。在IE8+及chrome下,利用DOM的clientWidth获取到的值是202,而在IE7下,获取到的是198,即,IE8+的width
属性为content-box,实际获取的clientWidth的值是border-box,而IE7下的width
属性为border-box,实际获取到的clientWidth的值是content-box。故在CSS文件中,加了一句box-sizing:border-box;
(CSS3)(IE7不支持)。这句主要是为了使得在IE8+上,获取到的clientWidth为200,解决因为条目数目变多(border的影响将凸显出来),而造成宽度不够分的问题。