John Nikolakis
John Nikolakis

Reputation: 229

CSS transition not running after element is moved to different parent

I got two list of elements and I want to move items from one list to another with a simple CSS transition.

The logic:


HTML

<ul id="list1">
    <li id="item1">Item 1</li>
    <li id="item2">Item 2</li>
</ul>

<ul id="list2">
    <li id="item3">Item 3</li>
    <li id="item4">Item 4</li>
</ul>

CSS

...
li {
    display: block;
    float: left;
    height: 80px;
    margin: 0 2px;
    -webkit-transition: all 1s ease-in-out;
       -moz-transition: all 1s ease-in-out;
         -o-transition: all 1s ease-in-out;
            transition: all 1s ease-in-out;
    width: 80px;
}

li.hidden {
    opacity: 0;
    width: 0;
}
...

JS

$(document).ready(function() {
    $('li').click(function() {
        var $item = $(this),
            parentId = $item.parent().attr('id'),
            newParentSelector = (parentId == 'list1') ? '#list2' : '#list1';


        $item.addClass('hidden');

        $item.one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(e) {
            $item.appendTo(newParentSelector);
            $item.removeClass('hidden');
        });

    });
});

When on the LI item the .hidden class is added the transition animation runs as expected. When the LI item is moved to another list and the .hidden class is removed the transition animation is not running but the item appears with correct opacity and width.

The weirder thing is that when I toggle the 'hidden' class of an item manually (i.e $('#item2').toggleClass('hidden'); ) both fade-in and fade-outanimations run.

The problem is demonstrated in this fiddle .

Upvotes: 3

Views: 683

Answers (1)

Bram Vanroy
Bram Vanroy

Reputation: 28485

I can't explain to you why this works, but setting a timeout (even if it is 1ms) seems to make it work.

See fiddle.

Relevant code

$item.one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(e) {
    $item.appendTo(newParentSelector);
    setTimeout(function() {
           $item.removeClass('hidden');
    }, 1);
});

EDIT 1: After testing it seems that Chrome and FF deal with this as we expect but IE10 doesn't want to. Setting a timeout of around 50 should do the trick.

Updated fiddle.

$item.one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend', function(e) {
    $item.appendTo(newParentSelector);
    setTimeout(function() {
            $item.removeClass('hidden');
    }, 50);
});

Upvotes: 1

Related Questions