【发布时间】:2009-07-15 14:31:16
【问题描述】:
在某些 div 上使用 jQuery“显示”和“隐藏”时,我在 Firefox 中得到了令人讨厌的“闪烁”效果。知道什么时候会发生这种情况吗?
【问题讨论】:
-
div 有背景图片吗?透明png?
-
@craigmoliver:您的代码示例会很好。
-
代码示例和您使用的浏览器和系统的描述会很好。
在某些 div 上使用 jQuery“显示”和“隐藏”时,我在 Firefox 中得到了令人讨厌的“闪烁”效果。知道什么时候会发生这种情况吗?
【问题讨论】:
取决于你所说的闪烁(如果它只在页面加载时闪烁),而不是这样做:
$(document).ready(function(){
$("hide").hide();
});
<div id="hide">My Hidden Text</div>
尝试在 CSS 中添加 display:none:
<div id="hide" style="display:none">My Hidden Text</a>
在允许 JavaScript 操作之前,CSS 已应用于 DOM,因此如果您这样做,加载页面时应该不会出现闪烁。
另外值得注意的是,在 Firefox 中,当您更改窗口大小(垂直)并且当前滚动位置接近或位于窗口底部时,存在一个导致窗口闪烁的错误。
【讨论】:
闪烁来自这行 jQuery 代码,在 show() 方法中:
var elem = jQuery("<" + tagName + " />").appendTo("body");
它这样做是为了检测它应该用于显示属性的 CSS,因为不同的标签会获得不同的值(div: block、span: inline、tr: table-row 等)。以这种方式操作 DOM 会导致闪烁。
用途:
jQuery('...').css('display','block');
这通常会做同样的事情。
【讨论】:
两个可能的原因:
除此之外,我们还需要一个样本。
【讨论】:
@Stephen:硬编码显示:CSS 中的 none 可能看起来很容易解决,但这可能是个坏主意。如果隐藏的内容对用户很重要,并且只是为了方便而在加载时隐藏(然后在用户单击按钮时显示),那么 display: none 将永久隐藏那些禁用 javascript 的内容.如果您担心可访问性,请不要使用这种方法...
【讨论】:
确实是这条线导致了闪烁。我编写了这个扩展来从 show 函数中删除该行。请注意,它总是将显示元素设置为“块”。
我最终以不同的方式解决了它。我使用了一个 span 元素并将其更改为 div。
/** fixes flicker in jQuery show function */
var fxAttrs = [
// height animations
[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
// width animations
[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
// opacity animations
[ "opacity" ]
];
function genFx( type, num ){
var obj = {};
jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function(){
obj[ this ] = type;
});
return obj;
}
(function($){
$.fn.extend({
show: function(speed,callback){
if ( speed ) {
return this.animate(genFx("show", 3), speed, callback);
} else {
for ( var i = 0, l = this.length; i < l; i++ ){
var old = jQuery.data(this[i], "olddisplay");
this[i].style.display = old || "";
if ( jQuery.css(this[i], "display") === "none" ) {
jQuery.data(this[i], "olddisplay", 'block');
}
}
// Set the display of the elements in a second loop
// to avoid the constant reflow
for ( var i = 0, l = this.length; i < l; i++ ){
this[i].style.display = jQuery.data(this[i], "olddisplay") || "";
}
return this;
}
}
});
})(jQuery);
【讨论】:
由于您提到了一些 div,如果您同时为多个 div 设置动画,可能会由于多次重绘而导致闪烁。
第一种解决方案,使用 settimeout 分割每个动画
第二个解决方案,将所有动画移动到 css 并切换类然后隐藏它。
将两者一起使用,如下所示进行显示和隐藏(使用过渡进行不透明度)
CSS
#you_div {
transition: opacity 0.4s ease-in-out;
}
JS
//To show
$('#you_div').css('opacity', '0');
$('#you_div').css('display', 'block');
setTimeout(function() {
$('#you_div').css('opacity', '1');
}, 50);
//To hide
$('#you_div').css('opacity', '0');
setTimeout(function() {
$('#you_div').css('display', 'none');
},400);
使用浏览器上的开发工具监控重绘。重绘越多,闪烁和滞后越多。
【讨论】:
我也注意到了这一点。我没有给你一个明确的答案,但你可以尝试为有问题的元素修改边框/填充/边距。
【讨论】: