【问题标题】:jQuery slide is jumpyjQuery 幻灯片跳动
【发布时间】:2009-08-26 15:12:36
【问题描述】:

我尝试使用 jQuery 的切换功能滑入和滑出 DIV,但结果在动画的开始和/或结束时总是跳跃。这是我使用的js代码:

$(document).ready(function(){
    $('#link1').click(
        function() {
            $('#note_1').parent().slideToggle(5000);
        }
);

还有 HTML:

<div class="notice">
    <p>Here's some text. And more text. <span id="link1">Test1</span></p>
    <div class="wrapper">
        <div id="note_1">
            <p>Some content</p>
            <p>More blalba</p>
        </div>
    </div>
</div>

您还可以在此处查看完整示例:jQuery Slide test

我通常使用 Mootools,我可以毫无问题地制作这张幻灯片。但是我正在 Django 中开始一个新项目,并且 Django 中的大多数应用程序都使用 jQuery。因此,在阅读了jQuery vs Mootools 之后,我决定这将是一个开始使用 jQuery 的好时机。所以我的第一个需要是滑动这个 DIV。而且它不能正常工作。

我进行了更多搜索,发现这是 jQuery 中的一个旧错误,其中边距和填充应用于 DIV。解决方案是将 DIV 包装在另一个 DIV 中。它并没有解决我的问题。

进一步搜索我发现了这篇文章Slidedown animation jumprevisited。它修复了一端的跳转,而不是另一端的跳转(Test2 in jQuery Slide test)。

在 Stack Overflow 上,我发现了这个 jQuery IE jerky slide animation。在 cmets 中,我看到问题出在 DIV 内的 P 标签上。如果我将 P 标签替换为 DIV 标签来解决问题,但这不是一个正确的解决方案。

最后我发现了这个Weird jQuery behavior slide。阅读它,我了解到通过从 P 标签切换到 DIV 解决的问题是 P 的边距(DIV 中不存在)和元素之间边距的折叠。因此,如果我将边距切换为填充,它可以解决问题。但是我放松了边距的折叠行为,折叠了我想要的。

老实说,我可以说我对 jQuery 的第一次体验并不是很好。如果我想使用 jQuery 中最简单的效果之一,我必须不使用正确的函数 (slideToggle),而是使用一些手工制作的代码并将 DIV 包装在另一个 DIV 中并将边距切换到填充,弄乱我的布局。

我错过了一个更简单的解决方案吗?

正如 krdluzni 建议的那样,我尝试使用 animate 方法编写自定义脚本。这是我的代码:

var $div = $('#note_2').parent();
var height = $div.height();

$('#link2').click(
    function () {
        if ( $div.height() > 0 ) {
            $div.animate({ height: 0 }, { duration: 5000 }).css('overflow', 'hidden');
        } else {
            $div.animate({ height : height }, { duration: 5000 });
        }

        return false;
});

但这也不起作用,因为 jQuery 总是在动画结束时将溢出设置为可见。因此,DIV 在动画结束时重新出现,但覆盖在其余内容上。

我也尝试了 UI.Slide(以及 Scale 和 Size)。它可以工作,但 DIV 下方的内容不会随动画移动。它只会在动画的结束/开始处跳转以填补空白。我不想要那个。

更新:

解决方案的一部分是在任何事情之前动态设置容器 DIV 的高度。这解决了一个跳跃。但不是利润率下降的原因之一。代码如下:

var parent_div = $("#note_1").parent();
parent_div.css("height", parent_div.height()+"px");
parent_div.hide();

第二次更新:

您可以在此页面上的 jQuery 自己的网站上看到错误(示例 B): Tutorials:Live Examples of jQuery

第三次更新:

用 jQuery 1.4 试过了,没有机会了 :-(

【问题讨论】:

  • 现在,我很难相信 jQuery 的“少写,多做”的口号。
  • 那么这绝对不是mootools等价功能的问题?
  • 你说得对,jQuery 在隐藏动画的末尾设置了 display:none 。 Mootools 不这样做。

标签: javascript jquery


【解决方案1】:

我发现始终有效的是设置一个不可见的 1px 边框:

border: 1px solid transparent;

无需固定宽度或高度或其他任何东西,动画不会跳跃。万岁!

【讨论】:

  • 此解决方案有效(您也可以将填充设置为 1px 以获得相同的结果),因为动画不会跳转。但我对此并不满意,因为通过设置边框或填充,它的真正作用是阻止子级和父级之间的边距折叠。而这种崩溃是我想要保留的东西(见我的问题)。
  • 对于禁用滑动元素的折叠边距不是问题的人来说,这是我找到的最佳解决方案。
  • 尽管我不太明白 - 这是一个非常简单的解决问题的方法 :) 我正在使用 Bootstrap 3
  • 这是没有意义但有效的事情之一。谢谢大佬。
  • 边框:0px 实心透明;也会解决这个问题,并且根本不会改变外观。
【解决方案2】:

解决办法是滑动div必须设置像素宽度。不要使用“auto”或“%”。你会有很好的结果!问题出在滑动 div 中的内联元素中。

但如果它们的宽度以 px 为单位,则高度将相同。试试吧。

【讨论】:

  • 我尝试设置滑动 DIV 的 px 宽度,但没有成功。我还尝试为滑动 DIV 中的每个元素设置以 px 为单位的宽度,但这也没有任何改变。我总是有神经质的行为。我确定问题在于边距的崩溃。我会尝试 jQuery 1.4 看看问题是否仍然存在......
  • 用 jQuery 1.4 试过了,没有机会了 :-(
  • 在 jQuery 1.6.2 上,这个问题仍然是个问题。值得庆幸的是,这个修复仍然有效!
  • 我使用 jQuery 成功测量和设置宽度。 $('.more').each(function() { $('.content', this).width( $(this).width() ); });
  • 如果您受到限制并且由于某种原因无法设置宽度,只需设置一个 1px 纯透明边框,它也可以。 border: 1px solid transparent;
【解决方案3】:

我今天遇到了这个问题。但是我确实注意到禁用所有 CSS 解决了这个问题。我也知道它之前运行良好,所以一定是最近的更改导致了这个问题。

原来我在 CSS 中使用了过渡来缓和悬停

从我添加的元素中删除这些过渡后,一切都很好。

因此,如果您有同样的问题,只需将这些行添加到您要添加的元素中:

-webkit-transition: none;
-moz-transition: none;
-o-transition: none;
-ms-transition: none;
transition: none;

(我可能滥用了过渡,不仅将它们添加到我想要过渡的元素中,而且将它们用于整个网站。)

【讨论】:

  • 刚刚遇到这个问题,我忘记了我对此有一个 CSS 转换,这导致 jQuery 出现问题。
  • 最佳答案。解决了我的问题。非常感谢
  • 谢谢!这是我的解决方法。
  • 解决了我的问题!
  • 感谢主!我在很多项目中都看到了这一点。现在我知道为什么我的 * { transition: all .5s ease;} 是一个糟糕的主意。
【解决方案4】:

尝试从所有元素中删除所有 CSS 边距。通常,生涩的动画来自动画框架没有考虑到的边距。

【讨论】:

  • 在我写它时,如果我从 P 标签中删除边距并用填充替换它,它会解决问题。但这对我来说不是一个合适的解决方案,因为它弄乱了我的布局,因为我失去了边距的折叠行为。
  • 他已经确定了导致它的原因,但他说他希望边距成为边距。删除它们违反了他的规范。
  • Etienne,您需要先使用 style() 命令删除正在动画的元素周围的边距,然后对其进行动画处理。您仍然会在顶部和底部元素处获得生涩的行为,并且必须专门处理这些边缘情况。
  • Sorry "then animate it, then" 应该写成:then animate it, then when reappearing you will need to restore the margins after the reappear animation done.
  • 亚当这可能是一个解决方案。但是对于我来说,在我想要滑动的 DIV 中使用带有边距的 P 标签看起来并不特殊。我认为问题的根源在于 jQuery 在动画结束时将 DIV 设置为 display:none。从显示中删除 DIV 及其所有边距。请参阅我对 krdluzni 的评论。
【解决方案5】:

父 div ".wrapper" 在您的情况 有填充时,就会发生抽搐。

填充在子 div 上,而不是在父 div 上。 jQuery 动画高度而不是填充。

例子:

  <div class="notice">
     <p>Here's some text. And more text. <span id="link1">Test1</span></p>
     <div class="wrapper" style="padding: 0">
        <div id="note_1" style="padding: 20px">
           <p>Some content</p>
           <p>More blalba</p>
        </div>
     </div>
   </div>

希望这会有所帮助。

【讨论】:

  • 不敢相信他们不接受这个作为答案。
  • 这是完美的,如果有一个带有填充的包装器。如果填充在动画元素上,则 1px 实心透明边框有效。我碰巧有这两种情况...
【解决方案6】:

我发现 animate() 是在 jQuery 中动画任何东西最可靠的方法(至少跨浏览器)。

这会动态地将内容包装在一个 div 中,然后使用其内部内容的高度为该 div 包装器的高度设置动画。

http://jsfiddle.net/BmWjy/13/

$('a').click(function(event) {
        event.preventDefault();
        xToggleHeight($(this).next());
});

//For each collapsible element.
$('.collapsible').each(function() {
        //Wrap a div around and set to hidden.
        $(this).wrap('<div style="height:0;overflow:hidden;visibility:hidden;"/>');
});

function xToggleHeight(el){
        //Get the height of the content including any margins.
        var contentHeight = el.children('.collapsible').outerHeight(true);
        //If the element is currently expanded.
        if(el.hasClass("expanded")){
                //Collapse
                el.removeClass("expanded")
                        .stop().animate({height:0},5000,
                        function(){
                                //on collapse complete
                                //Set to hidden so content is invisible.
                                $(this).css({'overflow':'hidden', 'visibility':'hidden'});
                        }
                );
        }else{
                //Expand
                el.addClass("expanded").css({'overflow':'', 'visibility':'visible'})
                        .stop().animate({height: contentHeight},5000,
                        function(){
                                //on expanded complete
                                //Set height to auto incase browser/content is resized afterwards.
                                $(this).css('height','');
                        }
                );
        }
}

【讨论】:

    【解决方案7】:

    您可以使用 animate 方法编写自定义动画。这将使您可以完全控制所有细节。

    【讨论】:

    • 这值得一试。我从不使用内置事件,除非它是一个微不足道的显示/隐藏。
    • 这就是我通过实现“Slidedown Animation jumprevisited”中显示的解决方案所做的。也许我必须对其进行调整以处理边距的崩溃。我会试试的。 JQuery 被认为很简单,而我想做的第一件简单的事情开始变得非常复杂。最后,我可能不得不重新实现 Mootools 解决方案以在 jQuery 中滑动(无显示:无,因此 DIV 保持在其边缘位置)。
    • 我用动画方法尝试了很多方法,问题总是一样的。如果我使用隐藏/显示,则将显示设置为无/阻止。但是使用 display: none,我失去了 DIV 的边距。如果我只使用高度为 0 的动画。在动画结束时,jQuery 将溢出设置为可见,覆盖应该隐藏的 DIV 内容。无论我尝试什么方式,总会遇到障碍:(
    • jQuery 不应该在自定义动画之后改变溢出,除非你告诉它...
    【解决方案8】:

    我注意到如果你的容器&lt;div&gt; 后面有一个&lt;br /&gt;,动画也会跳动。删除它解决了我的问题。

    【讨论】:

    • 谢谢,但在我的示例中,我没有任何
      。 :(
    【解决方案9】:

    css padding 和 jquery slideToggle 不能很好地协同工作。尝试框出填充。

    【讨论】:

      【解决方案10】:

      对于这个问题显然有很多不同的解决方案 - 根据您的布局,不同的解决方案会产生不同的结果。

      这是我所拥有的(精简)

      <div>
         <p>Text</p>
      </div>
      <div class="hidden">
         <p></p>
      </div>
      

      当我使用 jQuery 显示 &lt;div class="hidden"&gt; 时,&lt;p&gt; 元素上的边距会与上方 &lt;p&gt; 元素的边距一起折叠。

      我觉得这很奇怪,因为他们在不同的&lt;divs&gt;

      我的解决方案是消除&lt;p&gt; 底部的边距。在一侧设置边距可防止第一个 &lt;p&gt; 底部的边距与第二个 &lt;p&gt; 的顶部折叠。

      此解决方法解决了我的问题,可能适用于其他人,但可能不适用于所有人。

      【讨论】:

        【解决方案11】:

        您只需修改 effects.js 中的向上、向下效果,让它们考虑可能存在的边距或填充,然后调整他们认为元素的总大小以适​​应这些值...类似的东西......

        Effect.BlindDown = function(element) {
          element = $(element);
          var elementDimensions = element.getDimensions();
        
        //below*
          var paddingtop = parseInt(element.getStyle('padding-top'));
          var paddingbottom = parseInt(element.getStyle('padding-bottom'));
          var totalPadding = paddingtop + paddingbottom;
        
          if(totalPadding > 0)
          {
           elementDimensions.height = (elementDimensions.height - totalPadding);
          }
        //above*
        
          return new Effect.Scale(element, 100, Object.extend({
            scaleContent: false,
            scaleX: false,
            scaleFrom: 0,
            scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
            restoreAfterFinish: true,
            afterSetup: function(effect) {
              effect.element.makeClipping().setStyle({height: '0px'}).show();
            },
            afterFinishInternal: function(effect) {
              effect.element.undoClipping();
            }
          }, arguments[1] || { }));
        };
        

        【讨论】:

        • 感谢您的回答。当我有更多时间时,我会试试这个。但我可以说我不同意“You just have to...”中的just这个词。您提出的代码对于应该可以正常工作的函数(幻灯片)来说远非微不足道。对我来说,这个解决方案是修补 jQuery 幻灯片功能中的一个缺陷。我会适当地向他们的跟踪器添加一个错误。
        【解决方案12】:

        尝试将容器(在本例中为 .notice div)的“位置”属性设置为“相对”。

        为我工作。 来源:slideToggle height is "jumping"

        【讨论】:

        • 我刚试过这个,在我的情况下也不起作用。我尝试将positionrelative 设置为容器、滑动div、所有内容等,但动画仍然会跳转。
        【解决方案13】:

        这里有很多建议,也有很多关于什么是有效的来回。对我来说,行为问题是当展开容器的动画会过度展开然后反弹回正确的展开高度(所有这些都作为一个动画的一部分完成)。例如,动画最初会展开到 500 像素的高度,然后收缩到 450 像素。崩溃没有问题。

        有效的解决方案是在展开/折叠 div 中添加以下 CSS: 空白:nowrap;

        效果很好 - 平滑扩展至正确的高度。

        【讨论】:

          【解决方案14】:

          我遇到了同样的问题,但没有一个建议的解决方案适合我,所以我提出了一个完全消除对 slideToggle() 的依赖的解决方案。

          Spark Notes:正常加载页面,收集您要切换的每个元素的高度,将该高度存储在一个特殊的数据属性中,然后折叠每个元素。然后就像在元素的data-height 属性(展开)和零(折叠)之间更改max-height 一样简单。如果您想为元素添加额外的填充和边距等,我建议将它们存储在单独的 CSS 类中,以便使用 max-height 属性添加和删除。

          将 jQuery 放在要切换的元素之后,并允许它们在页面加载期间执行(这样您就不必看着它们全部加载然后折叠)。

          HTML

          <ul id="foo">
             <li>
                <h2>Click Me 1</h2>
                <div class="bar">Content To Toggle Here 1</div>
             </li>
             <li>
                <h2>Click Me 2</h2>
                <div class="bar">Content To Toggle Here 2</div>
             </li>
          </ul>
          

          CSS

          #foo>li>div.bar {transition: all 0.5s;
             overflow: hidden;}
          

          jQuery

          $('#foo h2').each(function(){
             var bar = $(this).siblings('.bar');
             bar.attr('data-height', bar.height()); //figure out the height first
             bar.css('max-height', '0px'); //then close vertically
          });
          $('#foo h2').click(function(){
             var bar = $(this).siblings('.bar');
             if ( bar .css('max-height') == '0px' ){ //if closed (then open)
                bar.css('max-height', bar.data('height') + 'px');
             } else { //must be open (so close)
                bar.css('max-height', '0px');
             }
          });
          

          这是一个有效的 JSFiddlehttp://jsfiddle.net/baacke/9WtvU/

          【讨论】:

            【解决方案15】:

            问题是您正在对父元素执行操作,这样做会删除与该元素相关的 CSS。

            您需要在 note1 上运行幻灯片,而不是在 note 1 的父级上运行。

            我遇到了同样的问题,并通过向下移动一个级别来解决它。

            【讨论】:

            • 滑动note1 而不是父级并不能解决我的问题。
            【解决方案16】:

            对我来说,从容器中删除最小高度解决了这个问题。

            【讨论】:

              【解决方案17】:

              如果您没有文档类型,您可以尝试添加一个文档类型,在我在 SO:jQuery slideToggle jumps around 上找到建议后,它在 IE8 上对我有用。他建议使用严格的 DTD,但我只是使用了 google.com 使用的文档类型:&lt;!doctype html&gt;,它解决了我的问题。

              【讨论】:

              • 感谢您的回答。我已经有一个 DOCTYPE(XHTML-Transitional,不严格)。但是你可以在 Jquery 自己的网站上看到这个错误,这里有一个 DOCTYPE 为 XHTML-strict 的页面(示例 B):docs.jquery.com/Tutorials:Live_Examples_of_jQuery
              • 试过 IE8 和 Chrome3。我看到两者都跳动并理解你的意思。看起来像是 jQuery 的问题。
              【解决方案18】:

              我遇到了同样的错误,花了几天时间才找到解决方案。问题是当元素被隐藏时 jquery 的高度错误。顶部修复它,您必须在隐藏之前获得高度,并使用自定义动画到该高度。这很棘手here for a better explanation

              【讨论】:

              • 不幸的是,它在我的情况下不起作用。这是我在Test 2jQuery Slide test 中使用的技术。
              【解决方案19】:

              我在导航标签中使用 div 时遇到了同样的问题 - 我的目标是在 div 悬停时显示一个无序列表(如果存在)。我的列表是动态创建的,因此它们没有固定值。

              解决方法如下:

              $("nav div").hover(
                function() { // i.e. onmouseover function
              
                  /****simple lines to fix a % based height to a px based height****/
                  var h = jQuery(this).find("ul").height(); //find the height
                  jQuery(this).find("ul").css("height", h); 
                                       //set the css height value to this fixed value
                  /*****************************************************************/
              
                  jQuery(this).find("ul").slideDown("500");
                },
                function(){ // i.e. onmouseout function
                  jQuery(this).find("ul").slideUp("500");
                });
              });
              

              【讨论】:

              • 相同的解决方案有“ Slidedown animation jumprevisited”。在我的情况下不起作用。
              【解决方案20】:

              今天遇到这个问题,看到这个问题,并根据我在这里看到的内容开始修补。我通过从包含 div 的 CSS 中删除 position:relative 解决了我们的棘手问题。之后就没有什么奇怪的了。我的 2 美分。

              【讨论】:

                【解决方案21】:

                确保您没有在全局范围内或在您的容器或任何包含的元素上设置 CSS 过渡规则。它也会导致抽搐。

                【讨论】:

                  【解决方案22】:

                  在我的情况下,我解决了它在元素中添加style="white-space:nowrap;" 以防止 jQuery 函数计算错误;除非需要换行,否则无需设置固定宽度。

                  【讨论】:

                    【解决方案23】:

                    我是这样使用slideDown()

                    $('#content').hide().delay(500).slideDown(500); 
                    

                    对我来说,它是主要容器 #content 元素。我把它隐藏起来,然后打电话给slideDown()。我删除了 CSS 中的 padding 属性,之后一切正常。它通常是边距、填充或百分比宽度,因此最简单的方法是注释掉每个属性并逐个测试它们以获得结果。

                    【讨论】:

                      【解决方案24】:

                      我刚刚了解到,如果展开/折叠元素中有浮动元素,也会出现此问题。在这种情况下,动画元素最后(仍在内部)的 clearfix (clear: both;) 可以摆脱它。

                      【讨论】:

                        【解决方案25】:

                        我有同样的问题。我通过添加这个来修复它:

                        .delay(100)

                        猜猜给它更多的时间思考会帮助它?

                        【讨论】:

                          【解决方案26】:

                          添加我的解决方案:原来我的问题是 flexbox(仅在 chrome 中)。我在父元素上设置了align-items: baseline;。将 align-self: center; 设置为我的 slideToggling 全角子元素,它立即清除了它。两个小时的用处很大。

                          【讨论】:

                            【解决方案27】:

                            对我来说,解决方案是,我有一个 CSS 样式定义,如下所示:

                            * {
                                transition: all .3s;
                            }
                            

                            删除这是解决方案!

                            【讨论】:

                              猜你喜欢
                              • 2015-04-21
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2014-04-02
                              • 2011-01-01
                              相关资源
                              最近更新 更多