Twitchy Twitchy - 1 month ago 5
CSS Question

CSS Transitions as a result of jQuery DOM Manipulations

How can I ensure CSS transitions will occur as a result of moving elements in the DOM with jQuery?

The following CSS transition is ignored when relying on a last-child state selector. The style updates as expected, but there is no transition time to that style.

<ul>
<li>A</li>
<li>B</li>
<li>C</li>
</ul>

li {
background-color: red;
}

li:last-child {
background-color: yellow;
transition: 3s ease;
}

// move list item to last place when clicked
$('li').click(function() {
var parent = $(this).parent();
$(this).detach().appendTo( parent );
});


JSFiddle

The only way I can seem to ensure a transition will occur is to add a class after a small setTimeout call, and not use a state selector.

li.activate {
background-color: yellow;
transition: 3s ease;
}

$('li').click(function() {
var item = $(this);
var parent = item.parent();
item.detach().appendTo( parent );
setTimeout( function() {
parent.children().removeClass('activate');
item.addClass('activate');
}, 5 );
});


JSFiddle

Answer

As you are just moving elements in the DOM tree, there's no visual state to transition from. However you can use CSS animations which are triggered also by creating a new element.

There is no need to .detach() first.

// move list item to last place when clicked
$('li').click(function() {
  var parent = $(this).parent();
  $(this).appendTo( parent );
});
li {
  background-color: red;
  height: 50px;
}

li:last-child {
  animation: pulse 1s 1;
  animation-fill-mode: forwards;
}

@keyframes pulse {
  0% {
    height: 50px;
  }
  100% {
    height: 90px;
    background-color: yellow;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li>A</li>
  <li>B</li>
  <li>C</li>
</ul>

Alternatively you can:

  1. Move the element (.appendTo)
  2. In the next loop (setTimeout, requestAnimationFrame, etc.) add a classname like 'last', which should in turn trigger the transition, because the element's CSS properties have changed from it's class-less state. (which you kind of figured out already…)
Comments