Shane
Shane

Reputation: 291

CSS3 Transitions - How to delay reset of the z-index property?

Basically, a "highlight" class is added to elements with class "edge" dynamically through javascript on mouseenter. The highlight class is removed on mouseleave. I want to transition the border-color of these elements. However, this "highlight" class also modifies the stack order. I want a z-index of 1 to be set on all highlighted edges before the transition begins (on mouseenter) and I want the z-index of 1 to be removed after the transition completes (on mouseleave). Currently the z-index property is reset immediately after the "highlight" class is removed.

Basic set up:

.edge {

    border-color: hsl(0, 0%, 40%);
    border-style: solid;
    border-width: (set appropriately in another selector);

    transition-duration: 1s;
    -moz-transition-duration: 1s;
    -o-transition-duration: 1s;
    -webkit-transition-duration: 1s;

    transition-property: border-color;
    -moz-transition-property: border-color;
    -o-transition-property: border-color;
    -webkit-transition-property: border-color;
}

.edge.highlight {
    border-color: hsl(0, 0%, 85%);
    z-index: 1;
}

First attempt (obviously the delay fixes the timing on one end and messes it up on the other):

.edge {
    border-color: hsl(0, 0%, 40%);
    border-style: solid;
    border-width: (set appropriately in another selector);

    transition-duration: 1s, 0;
    -moz-transition-duration: 1s, 0;
    -o-transition-duration: 1s, 0;
    -webkit-transition-duration: 1s, 0;

    transition-delay: 0, 1s;
    -moz-transition-delay: 0, 1s;
    -o-transition-delay: 0, 1s;
    -webkit-transition-delay: 0, 1s;

    transition-property: border-color, z-index;
    -moz-transition-property: border-color, z-index;
    -o-transition-property: border-color, z-index;
    -webkit-transition-property: border-color, z-index;
}

Any and all help is very much appreciated. Thanks in advance.

edit: Please keep in mind that the user can mouseenter/mouseleave on several different edges before the transitions have a chance to complete. Thanks.

Upvotes: 27

Views: 23536

Answers (4)

godblessstrawberry
godblessstrawberry

Reputation: 5068

If you're having troubles with z-index transition solution from @z0r - you can postpone z-index change via animation as an alternative, but transition worked better for me in Safari

.hasDelayedZIndex {
  animation: setZIndexWithDelay 0.01s 1s forwards;      
}

@keyframes setZIndexWithDelay {
  to {
    z-index: 1;
  }
}

Upvotes: 0

z0r
z0r

Reputation: 8585

You can use a delay, as Jcubed suggested, or the timing functions step-end and step-start. The trick is to use two different timing functions: stepped for z-index, and linear for opacity and other continuous properties.

edge {
    z-index: -1;
    opacity: 0;
    transition: z-index 0.5s step-end, opacity 0.5s linear;
}

edge.highlight {
    z-index: 1;
    opacity: 1;
    transition: z-index 0.5s step-start, opacity 0.5s linear;
}

Example: http://jsfiddle.net/cehHh/8/

Upvotes: 69

Py.
Py.

Reputation: 3599

You could use two classes, one for each transition (the first one for the color, then for the z-index). Note that the following is made using jQuery for convenience, and it's only for one edge. To do so for multiple edge, you'd need to store one timer per edge.

Given the following markup:

​<div class="edge"></div>​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

CSS:

.edge {
    width:40px;
    height:40px;
    border-color: hsl(0, 0%, 40%);
    border-style: solid;
    border-width: (set appropriately in another selector);

    transition-duration: 1s;
    -moz-transition-duration: 1s;
    -o-transition-duration: 1s;
    -webkit-transition-duration: 1s;

    transition-property: border-color;
    -moz-transition-property: border-color;
    -o-transition-property: border-color;
    -webkit-transition-property: border-color;
}

.edge.highlight {
    border-color: hsl(0, 0%, 85%);
    z-index: 1;
}
.edge.endHl{
    border-color: hsl(0, 0%, 65%);
    z-index: 1;
}

(I added a little color change on the second transition just to show it).

And the following JS:

var myTime = null;
function resetTime() {
    if (myTime !== null) {
        clearTimeout(myTime);
        myTime = null;
    }
}
$(".edge").mouseenter(function() {
    resetTime();
    $(this).addClass("highlight");
    $(this).removeClass("endHl");
});
$(".edge").mouseleave(function() {
    resetTime();
    myTime = setTimeout(function() {
        $(".edge").removeClass("endHl");
    },1000);
    $(this).removeClass("highlight");
    $(this).addClass("endHl");
});

It will remove the z-index only after 1 sec, and will apply only on the exit.

You can see it in action here: http://jsfiddle.net/TptP8/

Upvotes: 1

John Stimac
John Stimac

Reputation: 5491

Use transition-delay. You can make it so it rises on hover but waits a while before sinking on hover out by assigning a different delay time to the element when it is in its hover state.

Example: http://jsfiddle.net/vQqzK/1/

This works in chrome, not sure if it will work in other browsers.

https://developer.mozilla.org/en/CSS/transition-delay

Upvotes: 4

Related Questions