AngularJS - Slide Divs Up And Down With Z-Index Changes Isn't Being Respected

Problem

Please see the JSFiddle here which shows my issue: http://jsfiddle.net/mlippy/zkH7S/

I'm attempting to shuffle divs up and down a list with those divs moving up hiding the divs moving down. If you look at the fiddle, there are 5 different colored boxes that you can click to tell them to move to the top. If you click various boxes in various positions, you'll start to see the z-index of the boxes moving up not be higher than that of the boxes moving down. If you click the 3rd positioned box repeatedly, that's been a quality reproducer for me.

The angular directive myWidget is applying the indexes through classes which are being added / removed in chained addClass and removeClass calls. See below and the opposite version in the fiddle.

element.removeClass('moveDown').addClass('moveUp').css('top', (newValue * 45) + 'px'); 

I had thought that this meant the browser was going to complete the first chained call before moving onto the second (and so on). However in this case it doesn't appear to be doing so.

Also in the directive / below, you'll find a working solution using $timeout to delay the change to the css top value which triggers the transition. It's been commented out, but there are comments showing how to toggle to the solution in the two spots code needs to be changed. This feels like cheating / not the correct way for it to be done however. Hence the question here.

element.removeClass('moveDown').addClass('moveUp');
$timeout(function() {
    element.css('top', (newValue * 45) + 'px');
}, 350);

This is my first time using AngularJS, so feel free to let me know if I'm using things incorrectly or there's a better pattern which would fix my issue.

Thanks!

Problem courtesy of: mlippy

Solution

You're right, there is a better way to do it.

See, your code for transition affects all properties:

.widget.moveUp {
    z-index: 100!important;
    -webkit-transition: all 1s ease-in-out;
    -moz-transition: all 1s ease-in-out;
    transition: all 1s ease-in-out;
}
.widget.moveDown {
    z-index: 1!important;
    -webkit-transition: all 1s ease-in-out;
    -moz-transition: all 1s ease-in-out;
    transition: all 1s ease-in-out;
}

So my guess is that your transition to z-index is also taking 1 second to happen.

Guessing that, I've took the liberty to change these lines of code to target a transition only on the top property, which is the only one that should be affect in your case.

.widget {
    width: 100%;
    height: 40px;
    position: absolute;
    clear: both;
    z-index: 1;
    -webkit-transition: top 1s ease-in-out 0s;
    -moz-transition: top 1s ease-in-out 0s;
    transition: top 1s ease-in-out 0s;
}
.widget.moveUp {
    z-index: 100!important;
}
.widget.moveDown {
    z-index: 1!important;
}

Here, I updated your FIDDLE

Solution courtesy of: Matheus

Discussion

There is currently no discussion for this recipe.

This recipe can be found in it's original form on Stack Over Flow.