最近在做一个Button控件,这个控件不仅限于使用<button>标签做容器,还允许使用<span><div>设置<h1>这样的标签。但是,对容器类型的大容忍度的代价就是要协调好这些容器在不同浏览器下的不同表现。下面总结下需要处理的兼容问题:
1. <= IE7版本的浏览器,不支持box-sizing属性的设置,且,button的box-sizing展示效果是border-box,而其余类型元素的是content-box;
2. border-box展示的元素,要让文字居中,要满足下面的等式 :
lineHeight = height - borderTopWidth - borderBottomWidth
3. IE8浏览器下,如果是纯汉字文字,即便你使用上面的方法做了居中兼容,文字也会向上飘;
知道了这三点,解决它们,目标也就达成了。
问题1和2: 考虑IE7的低占有率,我考虑将IE7浏览器下的表现兼容统一成其他浏览器,即如果使用<button>做容器,并设置了height(这个是包含了border的),那我会把这个height加上border的宽度,使得它的表现看起来是content-box的。
问题3: 这个处理要个小窍门,既然纯汉字会飘上,那么我们就增加一个非汉字的字符,并把它隐藏起来。增加下面一段css:
[元素的class]:before { content: '.'; visibility: hidden; }
现在大致的解决方向已经知道,那么,在一个height可以动态设置的环境里,怎么动态的调整这些值呢?
首先,我们需要一个获取上下border尺寸的函数:
function getBorderInfo(dom) { var borderTop; var borderBottom; // IE支持 if (dom.currentStyle) { borderTop = parseInt(dom.currentStyle.borderTopWidth); borderBottom = parseInt(dom.currentStyle.borderBottomWidth); } // FF,Chrom支持 else if (window.getComputedStyle(dom, null)) { var style = window.getComputedStyle(dom, null); borderTop = Math.ceil(parseFloat(style.borderTopWidth)); borderBottom = Math.ceil(parseFloat(style.borderBottomWidth)); } return { borderTop: borderTop borderBottom: borderBottom } }
Tip:有一个问题需要注意一下,就是IE下有一个bug,对于非<button>的元素,在你还没有给这个元素定义height属性时,你使用currentStyle去获取border信息,得出来的结果是“medium”这种相对尺寸信息,其实这个是没有意义的。而我着实不想每次设置height的时候都去调用这么一个函数去重新计算border,所以这个函数,我只用在<button>上,并且只用一次就存起来。
经过验证,即便是<button>,在你不设置一个height给它的时候,它返回的尺寸也是不对的,似乎是默认值,比如“2px”。所以我最后只能把它放到了设置height之后。
接下来我要调整我们的height了。
function setHeight(dom, height) { dom.style.height = height+ 'px'; var lineHeight = value; dom.style.lineHeight = lineHeight + 'px'; // offsetHeight是元素包含了border和内容后的总高度 var offsetHeight = dom.offsetHeight; // 说明是border-box模式 if (offsetHeight === height) { // 那么我需要把它调整成content-box var borderInfo = getBorderInfo(dom); height = height + borderInfo.borderTop + borderInfo.borderBottom; dom.style.height = height + 'px'; } }
好了,这样就行了。当然,我这里没有考虑padding(因为我没设置。。。),不过如果有这个需要,其实也就是在加加减减的时候把padding算上而已。