交换<div>位置会导致CSS3过渡效果丢失

时间:2016-11-08 09:22:39

标签: javascript jquery css css3 css-transitions

我遇到了一个问题,这个问题似乎是因为改变了父母中两个<divs>的位置,基本上是重新排序。

这两个div都应用了transition css规则:

-webkit-transition: all .2s ease-in-out;
-moz-transition: all .2s ease-in-out;
transition: all .2s ease-in-out;

当我打电话给它交换位置时:

function swapElements(first, second) {
    $(first).insertBefore(second);
}

first元素没有浏览器应用的过渡效果,在与上一个/第二个元素交换后,它基本上没有动画效果。

这是一个问题,因为我正在收听转换结束回调,然后在<div>内进行更多工作(初始化图库):

if (Modernizr.csstransitions) {
        $(roomColumn).one('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function () {
           if (!gallery.hasClass('slick-initialized')) {
                $(gallery).slick({
                    lazyLoad: 'progressive',
                    slidesToShow: 1,
                    slidesToScroll: 1,
                    autoplay: false,
                    dots: false,
                    adaptiveHeight: false
                });
            }
        });
    }

由于浏览器没有为此元素进行转换,因此永远不会为此.one('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function (){});触发事件<div>,因此未对其进行初始化。

有没有人对可能导致此行为的原因有任何想法?

修改:Here is a very crude JS fiddle。您需要展开输出窗口,使其为四列。

正如您所看到的,单击前三个中的任何一个都可以获得动画效果,单击标记为<div>的行中的最后一个LAST ROOM,不会导致任何动画发生。

有趣的是,如果我将<div>交换代码包裹在setTimeout调用中,它可以正常运行,这似乎是一个时间问题,显然我不想依赖于此作为hacky但是,它也会导致div跳到不合适的位置。

1 个答案:

答案 0 :(得分:2)

问题出现是因为在交换之后,您还删除了原始类(对于小盒子显示)并替换为新类(对于较大的显示)。这三个都发生在一个阻塞呼叫中。无论何时添加元素,浏览器都需要触发重排,但在每个步骤之后它不会触发重排,因为这样做会影响性能。因此,回流发生在最后(在执行removeClass和addClass之后),因此只有一个元素具有在屏幕上绘制的新类 - 没有状态改变,因此也没有转换。

为了解决这个问题,我们 需要强制UA在交换后但在课程更改之前触发重排/重绘 。这可以用 两种方式 完成 - 一种是强制类更改语句进入不同的函数调用(使用setTimeout的匿名函数),另一种是通过迫使UA计算像clientHeight之类的东西(它们强制重绘,因为它们只能计算实际高度)。

Demo with setTimeout | Demo with clientHeight