I would like to make a css transition on an element which has display: none
set. Consider the following code:
Regarding the question on if this is in the spec, there is an interesting thread on the www-style@w3.org list here. I haven't read it all but it seems as they don't start animations from none
and that the transition spec needs to clarify that as well.
Update: I have asked the mail list and I got this link to the minutes of a work group meeting where it was decided that there should be no transition if the start state is display: none
.
To make sure that the transition is performed you must make sure that the value of the animated property is calculated before it is set to its new target. Values are normally not calculated when display is set to none. Here is a working example:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Fade</title>
<style>
.hidden { display: none }
.start { opacity: 0 }
.transition { opacity: 1; -webkit-transition: opacity 1s }
</style>
</head>
<body>
<div id='div' class="hidden">Test</div>
<script>
var elem = document.getElementById('div');
function ontransitionend(event) {
elem.className = null;
elem.removeEventListener('transitionend', ontransitionend);
}
elem.addEventListener('transitionend', ontransitionend);
elem.className = 'start';
window.getComputedStyle(elem).opacity;
elem.className = 'transition';
</script>
</body>
</html>
Note that you have to access the opacity property. It is not enough to call getComputedStyle()
!
There are several css properties that cannot be incremented in small steps (what is the value of display
25% of the way between none
and block
?), particularly those that have non numeric values. The workaround you are describing is pretty much the standard way of dealing with this. jQuery, for example, uses something similar in its fadeIn
and fadeOut
methods.
If you want to animate the transition from taking up no space to standard layout, you can transition the height
and width
properties.
You should not necessarily relay on transitionend
callbacks.
To show with a transition on the opacity property (or others) an hidden element that initially has display:none
, simply use inline style to set display:block
then remove your CSS class .hidden
to animate the element as you want:
CSS:
#foo {
display: none;
opacity: 1;
/*optional, other ending properties...*/
transition: opacity 1s;
}
.hidden {
opacity: 0;
/*optional, other starting properties...*/
}
HTML:
<div id="foo" class="hidden">
My test div
</div>
finally, the javascript part to show the element with a transition:
var elem = document.getElementById('foo');
elem.style.display = 'block';
elem.classList.remove('hidden');
the display: none mean that you could reach the element but first you should make sure that element has been rendered . you can use ready function in jquery or implemente it in javascript to make sure that the element is there . you could do the above by using : javascript(use timer to increase the opacity) or jquery as below
<html>
<head>
<meta charset="utf-8">
<title>CSS Transition From Hidden</title>
<script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
<script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
<style type="text/css">
div.hidden {
display: none;
opacity: 0;
}
</style>
<script type="text/javascript">
$.ready = function () {
$("#foo").fadeIn(2000);
}
</script>
</head>
<body>
<div id="foo" class="hidden">
My test div
</div>
</body>
</html>
I have the same issue and i dont think it should be considered an acceptable behavior by the browsers. The problem is not that anyone is trying to animate the actual display property. Its that you cannot have an element with display: none, update the property to inline or whatever and then animate the opacity for example, not even if you put a timeout for 10 seconds after the display has been updated.
My workaround right now is putting width and height to 0, overflow to hidden, updating these values and THEN update the animation attributes. At least it behaves more similar to display none than visibility hidden.
display:none jacks up the animation. It's a shame and I think should be addressed by browsers. I've gotten around the problem before by setting a z-index to -1, which hides the element, and if absolutely positioned also removes it from the static layout. You can actually transition z-index (though it doesn't really look like animate), therefore doesn't mess up the opacity animation.
This worked for me on my application, although I eventually had to use JavaScript to go ahead and set the display property from none to block because I eventually needed to use the fading element in a overflow:auto element, which when it wasn't hidden, created scroll bars at undesired times.