I have got a problem with a CSS3 animation.
.child {
opacity: 0;
display: none;
-webkit-transition: opacity 0.5s ease-in-out;
-moz-transit
One thing that I did was set the initial state's margin to be something like "margin-left: -9999px" so it does not appear on the screen, and then reset "margin-left: 0" on the hover state. Keep it "display: block" in that case. Did the trick for me :)
Edit: Save the state and not revert to previous hover state? Ok here we need JS:
<style>
.hovered {
/* hover styles here */
}
</style>
<script type="text/javascript">
$('.link').hover(function() {
var $link = $(this);
if (!$link.hasclass('hovered')) { // check to see if the class was already given
$(this).addClass('hovered');
}
});
</script>
If you are triggering the change with JS, let's say on click, there is a nice workaround.
You see the problem happens because the animation is ignored on display:none element but browser applies all the changes at once and the element is never display:block while not animated at the same time.
The trick is to ask the browser to render the frame after changing the visibility but before triggering the animation.
Here is a JQuery example:
$('.child').css({"display":"block"});
//now ask the browser what is the value of the display property
$('.child').css("display"); //this will trigger the browser to apply the change. this costs one frame render
//now a change to opacity will trigger the animation
$('.child').css("opacity":100);
Based on Michaels answer this is the actual CSS code to use
.parent:hover .child
{
display: block;
-webkit-animation: fadeInFromNone 0.5s ease-out;
-moz-animation: fadeInFromNone 0.5s ease-out;
-o-animation: fadeInFromNone 0.5s ease-out;
animation: fadeInFromNone 0.5s ease-out;
}
@-webkit-keyframes fadeInFromNone {
0% {
display: none;
opacity: 0;
}
1% {
display: block;
opacity: 0;
}
100% {
display: block;
opacity: 1;
}
}
@-moz-keyframes fadeInFromNone {
0% {
display: none;
opacity: 0;
}
1% {
display: block;
opacity: 0;
}
100% {
display: block;
opacity: 1;
}
}
@-o-keyframes fadeInFromNone {
0% {
display: none;
opacity: 0;
}
1% {
display: block;
opacity: 0;
}
100% {
display: block;
opacity: 1;
}
}
@keyframes fadeInFromNone {
0% {
display: none;
opacity: 0;
}
1% {
display: block;
opacity: 0;
}
100% {
display: block;
opacity: 1;
}
}
This workaround works:
define a “keyframe”:
@-webkit-keyframes fadeIn {
0% { opacity: 0; }
20% { opacity: 0; }
40% { opacity: 0.3; }
60% { opacity: 0.5; }
80% { opacity: 0.9; }
100% { opacity: 1; }
}
@keyframes fadeIn {
0% { opacity: 0; }
20% { opacity: 0; }
40% { opacity: 0.3; }
60% { opacity: 0.5; }
80% { opacity: 0.9; }
100% { opacity: 1; }
}
Use this “keyframe” on “hover”:
div a span {
display: none;
}
div a:hover span {
display: block;
-webkit-animation-name: fadeIn;
-webkit-animation-duration: 1s;
animation-name: fadeIn;
animation-duration: 1s;
}
I had the same problem. I tried using animations instead of transitions - as suggested by @MichaelMullany and @Chris - but it only worked for webkit browsers even if I copy-pasted with "-moz" and "-o" prefixes.
I was able to get around the problem by using visibility
instead of display
. This works for me because my child element is position: absolute
, so document flow isn't being affected. It might work for others too.
This is what the original code would look like using my solution:
.child {
position: absolute;
opacity: 0;
visibility: hidden;
-webkit-transition: opacity 0.5s ease-in-out;
-moz-transition: opacity 0.5s ease-in-out;
transition: opacity 0.5s ease-in-out;
}
.parent:hover .child {
position: relative;
opacity: 0.9;
visibility: visible;
}
I know, this is not really a solution for your question, because you ask for
display + opacity
My approach solves a more general question, but maybe this was the background problem that should be solved by using display
in combination with opacity
.
My desire was to get the Element out of the way when it is not visible. This solution does exactly that: It moves the element out of the away, and this can be used for transition:
.child {
left: -2000px;
opacity: 0;
visibility: hidden;
transition: left 0s 0.8s, visibility 0s 0.8s, opacity 0.8s;
}
.parent:hover .child {
left: 0;
opacity: 1;
visibility: visible;
transition: left 0s, visibility 0s, opacity 0.8s;
}
This code does not contain any browser prefixes or backward compatibility hacks. It just illustrates the concept how the element is moved away as it is not needed any more.
The interesting part are the two different transition definitions. When the mouse-pointer is hovering the .parent
element the .child
element needs to be put in place immediately and then the opacity will be changed:
transition: left 0s, visibility 0s, opacity 0.8s;
When there is no hover, or the mouse-pointer was moved off the element, one has to wait until the opacity change has finished before the element can be moved off screen:
transition: left 0s 0.8s, visibility 0s 0.8s, opacity 0.8s;
Moving the object away will be a viable alternative in a case where setting display:none
would not break the layout.
I hope I hit the nail on the head for this question although I did not answer it.