其实这是一个老问题了,s visibility:hidden 与 display:none 共同点就是都会似的元素不可见。但是 visibility:hidden 的DOM元素是占用空间的,会挤占其他元素的位置,宽度和高度边框边距等都不会发生变化,所以使用 offsetWidth等属性获取的值不会发生变化。 但是display:none 就完全不同了,在DOM树中完全不会渲染,就相当于不存在这个DOM一样,所以使用 offsetWidth 等获取到的结果都是0。 明白了这些,下面我们来看一个简单的应用。
在IE8中使用angular和bootstrap3的时候,发现引入 ui.bootstrap之后鼠标划过对应的tr(列表布局使用的table>tr)的时候会出现闪动的情况,查找bootstrap的源码就可以发现其实它是在 tr的后面添加了div,这样在IE8中就会导致整个布局错乱,那这里我们只能自己动手来写一个类似的功能了,这里就牵扯到计算隐藏元素高度的问题。
首先在body结束标签之前,我们新增一个 tootip的div,代码如下(其实就是 bootstrap 中 tooltip插件里面的一个参数 template):
<div id="tooltips" class="tooltip top"> <div class="tooltip-arrow"></div> <div class="tooltip-inner"></div> </div>
增加如下代码后,bootstrap默认的css会直接渲染为tooltip的样式,这里为了方便,我们就不再更改默认的class,然后我们让这个提示框显示到对应元素的上方,中间位置,但是问题来了,tooltip-inner里面的内容是不固定的,也就是说这里面的内容高度是不确定的,因此我们根据元素位置获取的top值在这里需要经过计算,减去这里的tooltip的高度才能正确加载到文档的对应位置。所以在鼠标移开的事件中就必须使用visibility:hidden 如果使用display:none, 再次获取tooltip的高度会发现高度为0了,看代码吧。
如果使用display:none (jq中的 hide()方法)
$.fn.tips = function(content){ var $tt = $('#tooltips'), $ttinner = $('.tooltip-inner'), pos = $(this).offset(), w = parseInt($(this).outerWidth(),10); $ttinner.html(content); var calcWidth = parseInt($tt.outerWidth(), 10); var h = parseInt($tt.outerHeight(),10), l = parseInt(pos.left)*1 + (w - calcWidth)*0.5; $tt.css({left:l+'px',top:(pos.top-h)+'px'}).fadeIn(100); } $.fn.tipshide = function(){ $('#tooltips').hide(); }
上面代码只有第一次会正确显示提示框,第二次的时候将无法正确显示,下面是修复后的
$.fn.tips = function(content){ var $tt = $('#tooltips'), $ttinner = $('.tooltip-inner'), pos = $(this).offset(), w = parseInt($(this).outerWidth(),10); $ttinner.html(content); var calcWidth = parseInt($tt.outerWidth(), 10); var h = parseInt($tt.outerHeight(),10), l = parseInt(pos.left)*1 + (w - calcWidth)*0.5; $tt.css({left:l+'px',top:(pos.top-h)+'px', visibility:"visible"}).fadeIn(100); } $.fn.tipshide = function(){ $('#tooltips').css("visibility","hidden"); }