在jquery中使用hide和show时不需要的“闪烁”效果

时间:2022-11-20 15:12:09

I'm getting an annoying "flickering" effect in Firefox when using jQuery "show" and "hide" on some div's. Any idea when this could be happening?

当在一些div上使用jQuery“show”和“hide”时,我在Firefox中遇到了令人讨厌的“闪烁”效果。有什么想法可以发生吗?

8 个解决方案

#1


Depending on what you mean by flicker (if it only flickers when the page loads), instead of doing:

取决于闪烁的含义(如果它只在页面加载时闪烁),而不是:

$(document).ready(function(){
   $("hide").hide();
});

<div id="hide">My Hidden Text</div>

Try adding display:none in the CSS:

尝试在CSS中添加display:none:

<div id="hide" style="display:none">My Hidden Text</a>

CSS is applied to the DOM before even JavaScript is allowed to manipulate it, so if you do this, there should be no flicker when you load the page.

在允许JavaScript操作之前,CSS应用于DOM,因此如果这样做,加载页面时应该没有闪烁。

Also of note, in Firefox, there is a bug that causes the window to flicker when you change the size of the window (vertically), and the current scroll position is close or at the bottom of the window.

另外值得注意的是,在Firefox中,当您更改窗口大小(垂直)并且当前滚动位置接近或位于窗口底部时,会出现导致窗口闪烁的错误。

#2


The flicker comes from this line of the jQuery code, in the show() method:

闪烁来自jQuery代码的这一行,在show()方法中:

 var elem = jQuery("<" + tagName + " />").appendTo("body"); 

It does that to detect the CSS it should use for the display attribute, since different tags get different values (div: block, span: inline, tr: table-row, etc). Manipulating the DOM in this way causes the flicker.

它可以检测它应该用于display属性的CSS,因为不同的标签会得到不同的值(div:block,span:inline,tr:table-row等)。以这种方式操作DOM会导致闪烁。

Use:

jQuery('...').css('display','block');

which will generally do the same thing.

这通常会做同样的事情。

#3


Two possible reasons:

两个可能的原因:

  1. Hiding and showing is causing the scrollbar to appear and disappear, which changes the page width; or
  2. 隐藏和显示导致滚动条出现和消失,这会改变页面宽度;要么

  3. The div appearing and disappearing changes the width and/or height calculations.
  4. 出现和消失的div改变宽度和/或高度计算。

Other than that, we'd need a sample.

除此之外,我们需要一个样本。

#4


@Stephen: Hard-coding display: none in the CSS may seem like an easy fix, but it's potentially a bad idea. If the hidden content is important to the user, and simply being hidden on load for convenience (and is then displayed when the user, for example, clicks on a button), then display: none will permanently hide the content from those with javascript disabled. If accessibility is a concern for you then don't use this approach...

@Stephen:硬编码显示:CSS中没有一个可能看起来像一个简单的修复,但它可能是一个坏主意。如果隐藏内容对用户很重要,只是为了方便而隐藏在加载中(然后在用户点击按钮时显示),则显示:none将永久隐藏禁用javascript的内容。如果您可以关注可访问性,那么请不要使用此方法...

#5


It is indeed this line that causes the flicker. I wrote this extension to remove the line from the show function. Note that it always sets the display element to 'block'.

确实是这条线会导致闪烁。我写了这个扩展来从show函数中删除该行。请注意,它始终将显示元素设置为“阻止”。

I eventually solved it differently. I used a span element and changed it to a div.

我最终解决了不同的问题。我使用了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);

#6


Since you had mentioned some divs, if you are animating more than one div at the same time can cause flickering due to multiple repaints.

既然你已经提到了一些div,如果你同时动画多个div可能会因多次重绘而导致闪烁。

1st solution, use settimeout to split each animation

第一个解决方案,使用settimeout来分割每个动画

2nd solution, move all the animation to css and just toggle the class and then hide it.

第二个解决方案,将所有动画移动到css,只需切换类然后隐藏它。

And use both together as follows for show and hide (using transition for opacity)

并使用如下两者一起显示和隐藏(使用不透明度的过渡)

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);

Monitor repaints using devtools on your browser. The more the repaint, more flickering and lags.

使用浏览器上的devtools监控重绘。重画更多,更闪烁和滞后。

#7


I've noticed this as well. I don't have a definite answer for you, but you might try tinkering with border/padding/margin for the element in question.

我也注意到了这一点。我没有给你一个明确的答案,但你可能会尝试修补相关元素的边框/填充/边距。

#8


Per John Resig in reponse to a similar complaint on the Jquery Google Group here

Per John Resig在这里回应了对Jquery Google Group的类似投诉

Which browser? If you're in IE, then this flicker is because your page is in Quirks mode instead of Standards mode (you'll need to provide a correct DOCTYPE in order to trigger this).

哪个浏览器?如果您在IE中,那么这种闪烁是因为您的页面处于Quirks模式而不是标准模式(您需要提供正确的DOCTYPE才能触发此操作)。

Also this post seems to point to the same solution.

此帖也似乎指向了相同的解决方案。

#1


Depending on what you mean by flicker (if it only flickers when the page loads), instead of doing:

取决于闪烁的含义(如果它只在页面加载时闪烁),而不是:

$(document).ready(function(){
   $("hide").hide();
});

<div id="hide">My Hidden Text</div>

Try adding display:none in the CSS:

尝试在CSS中添加display:none:

<div id="hide" style="display:none">My Hidden Text</a>

CSS is applied to the DOM before even JavaScript is allowed to manipulate it, so if you do this, there should be no flicker when you load the page.

在允许JavaScript操作之前,CSS应用于DOM,因此如果这样做,加载页面时应该没有闪烁。

Also of note, in Firefox, there is a bug that causes the window to flicker when you change the size of the window (vertically), and the current scroll position is close or at the bottom of the window.

另外值得注意的是,在Firefox中,当您更改窗口大小(垂直)并且当前滚动位置接近或位于窗口底部时,会出现导致窗口闪烁的错误。

#2


The flicker comes from this line of the jQuery code, in the show() method:

闪烁来自jQuery代码的这一行,在show()方法中:

 var elem = jQuery("<" + tagName + " />").appendTo("body"); 

It does that to detect the CSS it should use for the display attribute, since different tags get different values (div: block, span: inline, tr: table-row, etc). Manipulating the DOM in this way causes the flicker.

它可以检测它应该用于display属性的CSS,因为不同的标签会得到不同的值(div:block,span:inline,tr:table-row等)。以这种方式操作DOM会导致闪烁。

Use:

jQuery('...').css('display','block');

which will generally do the same thing.

这通常会做同样的事情。

#3


Two possible reasons:

两个可能的原因:

  1. Hiding and showing is causing the scrollbar to appear and disappear, which changes the page width; or
  2. 隐藏和显示导致滚动条出现和消失,这会改变页面宽度;要么

  3. The div appearing and disappearing changes the width and/or height calculations.
  4. 出现和消失的div改变宽度和/或高度计算。

Other than that, we'd need a sample.

除此之外,我们需要一个样本。

#4


@Stephen: Hard-coding display: none in the CSS may seem like an easy fix, but it's potentially a bad idea. If the hidden content is important to the user, and simply being hidden on load for convenience (and is then displayed when the user, for example, clicks on a button), then display: none will permanently hide the content from those with javascript disabled. If accessibility is a concern for you then don't use this approach...

@Stephen:硬编码显示:CSS中没有一个可能看起来像一个简单的修复,但它可能是一个坏主意。如果隐藏内容对用户很重要,只是为了方便而隐藏在加载中(然后在用户点击按钮时显示),则显示:none将永久隐藏禁用javascript的内容。如果您可以关注可访问性,那么请不要使用此方法...

#5


It is indeed this line that causes the flicker. I wrote this extension to remove the line from the show function. Note that it always sets the display element to 'block'.

确实是这条线会导致闪烁。我写了这个扩展来从show函数中删除该行。请注意,它始终将显示元素设置为“阻止”。

I eventually solved it differently. I used a span element and changed it to a div.

我最终解决了不同的问题。我使用了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);

#6


Since you had mentioned some divs, if you are animating more than one div at the same time can cause flickering due to multiple repaints.

既然你已经提到了一些div,如果你同时动画多个div可能会因多次重绘而导致闪烁。

1st solution, use settimeout to split each animation

第一个解决方案,使用settimeout来分割每个动画

2nd solution, move all the animation to css and just toggle the class and then hide it.

第二个解决方案,将所有动画移动到css,只需切换类然后隐藏它。

And use both together as follows for show and hide (using transition for opacity)

并使用如下两者一起显示和隐藏(使用不透明度的过渡)

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);

Monitor repaints using devtools on your browser. The more the repaint, more flickering and lags.

使用浏览器上的devtools监控重绘。重画更多,更闪烁和滞后。

#7


I've noticed this as well. I don't have a definite answer for you, but you might try tinkering with border/padding/margin for the element in question.

我也注意到了这一点。我没有给你一个明确的答案,但你可能会尝试修补相关元素的边框/填充/边距。

#8


Per John Resig in reponse to a similar complaint on the Jquery Google Group here

Per John Resig在这里回应了对Jquery Google Group的类似投诉

Which browser? If you're in IE, then this flicker is because your page is in Quirks mode instead of Standards mode (you'll need to provide a correct DOCTYPE in order to trigger this).

哪个浏览器?如果您在IE中,那么这种闪烁是因为您的页面处于Quirks模式而不是标准模式(您需要提供正确的DOCTYPE才能触发此操作)。

Also this post seems to point to the same solution.

此帖也似乎指向了相同的解决方案。