CSS animation-duration issue, on state change animation becomes instantaneous - css

I am encountering a problem where an animation that is set to run on click is happening instantly when it should have a delay, when I change the state from false to true manually I can see the transition working fine, however when implementing the onClick feature and clicking the element it does not have the animation-duration being applied.
does anyone know a work around or a best practise to getting this working?
Main.js
import React, { useState } from "react";
export default function Main() {
const [isToggled, setIsToggled] = useState(false)
function handleToggle() {
setIsToggled(!isToggled)
}
return (
<div className="menu"
onClick={handleToggle}
>
<img src={require("../resources/menu-dropdown.png")}
className={isToggled ? "menu--dropdown top--tile motion" : "menu--dropdown top--tile reverse--motion"}
/>
<img src={require("../resources/menu-dropdown.png")}
className={isToggled ? "menu--dropdown bottom--tile motion" : "menu--dropdown bottom--tile reverse--motion"}
/>
</div>
)
}
styles.css
.menu--dropdown {
width: 15%;
position: absolute;
}
.top--tile {
top: -10%;
right: -95%;
}
#keyframes top--motion {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(45deg);
transform-origin: 30% 70%;
}
}
.top--tile.motion {
animation-name: top--motion;
animation-duration: 0.3s;
animation-fill-mode: forwards;
}
.top--tile.reverse--motion {
animation-direction: reverse;
animation-name: top--motion;
animation-duration: 0.3s;
animation-fill-mode: forwards;
}
#keyframes bottom--motion {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-45deg);
transform-origin: 40% 60%;
}
}
.bottom--tile {
top: -7.5%;
right: -95%;
}
.bottom--tile.motion {
animation-name: bottom--motion;
animation-duration: 0.3s;
animation-fill-mode: forwards;
}
.bottom--tile.reverse--motion {
animation-direction: reverse;
animation-name: bottom--motion;
animation-duration: 0.3s;
animation-fill-mode: forwards;
}

Related

Is there a conflict rule in css? My fadein keyframes works fine but my slidedown doesn't

Im using react and css. In my css file I create 2 animations:
#keyframes fadein {
0% {
visibility: hidden;
opacity: 0;
}
50% {
opacity: 0.5;
}
100% {
visibility: visible;
opacity: 1;
}
}
#keyframes slidedown {
0% {
transform: translateY(0%);
}
100% {
transform: translateY(30%);
}
}
.welcome__text {
padding: 3rem;
animation:
/* slidedown 2s ease 0s 1 normal forwards; => This one doesn't work */
/* fadein 1s ease-in 0s 1 normal forwards; => This one works */
}
here is my react file :
const Home = () => {
return (
<div className='homepage'>
<div className='welcome__text'>
<h1>Welcome</h1>
<h3> to Net's Web Game </h3>
</div>
</div>
)
}
export default Home;
My fadein keyframes works fine but my slidedown doesn't. And I don't know why. Is there any conflict css rule ?
If you're calling 2 animations on 1 element you need to separate them with commas, otherwise the last one (fadein) will just take priority as CSS is read from top to bottom, thus resulting in only 1 animation. For the animation properties, just separate them with commas as well:
#keyframes fadein {
0% {
visibility: hidden;
opacity: 0;
}
50% {
opacity: 0.5;
}
100% {
visibility: visible;
opacity: 1;
}
}
#keyframes slidedown {
0% {
transform: translateY(0%);
}
100% {
transform: translateY(30%);
}
}
.welcome__text {
padding: 3rem;
animation: slidedown 2s, fadein 1s;
animation-fill-mode: forwards;
animation-timing-function: ease 0s, ease-in 0s;
animation-direction: normal;
/* slidedown 2s ease 0s 1 normal forwards; => This one doesn't work */
/* fadein 1s ease-in 0s 1 normal forwards; => This one works */
}
<div class="welcome__text">hey there!</div>

CSS fade transition (no jQuery)

I'm trying to create a visual transition between content changes in a toy SPA I'm writing. To that end, I define a simple class for animating the opacity of an element.
.fade {
transition: opacity 1.5s;
}
In my render function, I now change the opacity of my outlet div after content changes like so:
function render(content) {
var outlet = document.getElementById("outlet");
outlet.classList.remove("fade");
outlet.style.opacity = 0;
outlet.innerHTML = content;
outlet.classList.add("fade");
outlet.style.opacity = 1;
}
Unfortunately, the animation never fires. When I delay changing the opacity to 1 via setTimeout for 10ms, say, it works sometimes if I don't change the content again while the animation is still running, indicating a timing issue/race condition.
I used a similar approach in the past to fade out messages, but there I intentionally delayed changing the opacity by a few seconds so users could read the message before it starts fading out.
Pure CSS animation fadeIn
li {
position: absolute;
top: 50%;
left: 50%;
margin-top: -75px;
}
.logo {
width: 300px;
height: 150px;
background: red;
margin-left: -150px;
z-index: 30;
-webkit-animation: fade-in-slogan 4s .2s ease-in forwards;
-moz-animation: fade-in-slogan 4s .2s ease-in forwards;
animation: fade-in-slogan 4s .2s ease-in forwards;
}
.menu {
width: 600px;
height: 150px;
background: blue;
margin-left: -300px;
opacity: 0;
-webkit-animation: fade-in-menu 3s 4s ease-out forwards;
-moz-animation: fade-in-menu 3s 4s ease-out forwards;
animation: fade-in-menu 3s 4s ease-out forwards;
}
#-webkit-keyframes fade-in-slogan {
0% { opacity: 0; }
30% { opacity: 1; }
50% { opacity: 1; }
70% { opacity: 1; }
100% { opacity: 0; }
}
#-webkit-keyframes fade-in-menu {
0% { display: block; opacity: 0; }
30% { display: block; opacity: .3; }
60% { display: block; opacity: .6; }
80% { display: block; opacity: .8; }
100% { display: block; opacity: 1; }
}
<ul class"main">
<li class="logo"></li>
<li class="menu"></li>
</ul>
Try this, I hope this will solve the issue
.fade{
animation-name: example;
animation-duration: 4s;}
#keyframes example {
from {opacity:1}
to {opacity:0;}
}
div{
width:200px;
height:200px;
background:#000;
}
<html>
<head>
</head>
<body>
<div class="fade"></div>
</body>
</html>
I've solved it now inspired by Muhammad's answer. I defined the fade class as follows:
.fade {
animation-name: fadein;
animation-duration: 1.25s;
#keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
}
Then in the render function, I do
function render(content) {
outlet.classList.remove("fade");
outlet.innerHTML = "";
setTimeout(() => {
outlet.classList.add("fade");
outlet.appendChild(content);
}, 100);
}
Even though this adds an additional delay before the new content actually starts to fade in, it seems the most elegant and concise solution to me.

how animation-direction works in css3 animation?

As i understand, when i change the animation-direction from normal to reverse during a specific animation, the element will move towards the opposite direction right away starting from where it is now.But it seems i am wrong , here is the http://codepen.io/johnwaynerui/pen/bZvRLm When i click the reverse button, the circle does not turn around right away and moving towards the opposite direction. Are there something i misunderstand?
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"> </script>
<div id="circle"></div>
<button id='reverse'>reverse</button>
#keyframes move-right {
0% {
transform: translateX(0px);
}
20% {
transform: translateX(200px);
}
40% {
transform: translateX(400px);
}
60% {
transform: translateX(600px);
}
80% {
transform: translateX(800px);
}
100% {
transform: translateX(1000px);
}
}
#circle {
height: 50px;
width: 50px;
border-radius:25px;
background-color: teal;
-webkit-animation-duration: 20s;
-webkit-animation-timing-function: linear;
-webkit-animation-name: move-right;
-webkit-animation-iteration-count: infinite;
animation-fill-mode: both;
position:absolute;
left:30%;
top:20%;
}
#circle.reverse {
animation-direction: reverse;
}
$('#reverse').click(function () {
$('#circle').toggleClass('reverse');
});
You can check the documentation for animation-direction here.
It clearly states that, for a reverse value:
The animation plays backward each cycle. Each time the animation cycles, the animation resets to the end state and starts over again.
As per my understanding, the moment you add animation-direction: reverse; to your animation, it goes in reverse direction mode that means the end-point of original animation becomes its start-point and vice-versa. So, if your animation has run first 20% and you change its animation-direction to reverse its start and end-points get interchanged, and it suddenly jumps to the 20% point relative to these changed end-points. That's why you notice that your circle suddenly jumps to far right and then continues its movement towards left.
$('#reverse').click(function () {
$('#circle').toggleClass('reverse');
});
#keyframes move-right {
0% {
transform: translateX(0px);
}
20% {
transform: translateX(200px);
}
40% {
transform: translateX(400px);
}
60% {
transform: translateX(600px);
}
80% {
transform: translateX(800px);
}
100% {
transform: translateX(1000px);
}
}
#circle {
height: 50px;
width: 50px;
border-radius:25px;
background-color: teal;
-webkit-animation-duration: 20s;
-webkit-animation-timing-function: linear;
-webkit-animation-name: move-right;
-webkit-animation-iteration-count: infinite;
animation-fill-mode: both;
position:absolute;
left:30%;
top:20%;
}
#circle.reverse {
animation-direction: reverse;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"> </script>
<div id="circle"></div>
<button id='reverse'>reverse</button>

Css3 animation scale and translate use maintime

I have some problem with animations. I'm writing steam animation and I need use translate and scale main time. I write some example you can see that it doesn't work. If you have time please help to do it correctly thanks.
html
<img src="https://lh3.googleusercontent.com/-uU_C0PBe64k/VSd6800h1bI/AAAAAAAAFM8/hp-vH8wT3U4/w63-h57-no/steam.png" />
css
#mixin steamLeft($speed, $delay) {
-webkit-animation-name: steamLeft;
animation-name: steamLeft;
animation-duration: $speed;
animation-delay: $delay;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
img {
position: absolute;
top: 50px;
left: 100px;
width: 63px;
height: 57px;
#include steamLeft(2s,0);
}
#keyframes steamLeft {
0% {
transform: translateX(0) scale(0);
}
10% {
transform: translateX(10px) scale(0.5);
}
20% {
transform: translateX(20px) scale(1);
}
}
example
also css write only for firefox on chrom it doesn't work

CSS3: Smooth transition between animations change on :hover

I have an elements that has infinite css3 animation that is changed to another infinite animation when element is hovered. Everything is ok, but sometimes animation changing is too bouncy, is there a way to make transition between animations smooth (maybe bringing element to the initial state between animations) on mouseenter and mouseleave? The starting and ending states of both animations are the same.
#keyframes first-animation {
0% { transform: scale3d(1,1,0);}
50% { transform: scale3d(0.8,0.8,0); }
100% { transform: scale3d(1,1,0); }
};
#keyframes second-animation {
0% { transform: scale3d(1,1,0); }
70% { transform: scale3d(0.7,0.7,0); }
80% { transform: scale3d(0.9,0.9,0); }
100% { transform: scale3d(1,1,0); }
};
div{
animation: first-animation 1.7s ease-in-out infinite;
}
div:hover, div:focus{
animation: second-animation 1.1s ease-in-out infinite;
}
I don't think that it can be achieved using the scale transforms.
You can do a trick and change from scale() to translateZ(). When a perspective is applied, the net effect will be also a scale. But the interesting point is than setting perspective to a high value, this scale effect can be made very small. And perspective is an animatable property.
The downside is that we will need to add 2 wrap around layers... but the final result is this. I have kept the original version to compare
#keyframes first-animation {
0% { transform: scale(1,1);}
50% { transform: scale(0.8,0.8); }
100% { transform: scale(1,1); }
}
#keyframes second-animation {
0% { transform: scale(1,1); }
70% { transform: scale(0.7,0.7); }
80% { transform: scale(0.9,0.9); }
100% { transform: scale(1,1); }
}
.sample {
background-color: lightblue;
animation: first-animation 1.7s ease-in-out infinite;
}
.sample:hover {
animation: second-animation 1.1s ease-in-out infinite;
}
.dim {
width: 200px;
height: 200px;
}
.base1 {
perspective: 1000px;
transition: perspective 2s ease-out;
position: absolute;
left: 300px;
top: 10px;
}
.base1:hover {
perspective: 9999px;
}
.base2 {
width: 100%;
height: 100%;
animation: animation1 1.7s ease-in-out infinite;
perspective: 9999px;
transition: perspective 2s ease-in;
}
.base1:hover .base2 {
perspective: 1000px;
}
.inner {
width: 100%;
height: 100%;
background-color: lightgreen;
animation: animation2 1.1s ease-in-out infinite;
transform-style: preserve-3d;
perspective: 99999px;
}
#keyframes animation1 {
0% { transform: translateZ(0px);}
50% { transform: translateZ(-200px); }
100% { transform: translateZ(0px); }
}
#keyframes animation2 {
0% { transform: translateZ(0px);}
70% { transform: translateZ(-300px); }
80% { transform: translateZ(-100px); }
100% { transform: translateZ(0px); }
}
<div class="sample dim">SAMPLE</div>
<div class="base1 dim">
<div class="base2">
<div class="inner">DEMO</div>
</div>
</div>
In order to get the desired effect then you will need to use the css3 animation events. in this case you need to use "AnimationIteration". So you can fire an event after an iteration. I have added a class to the end of this event for the second animation.
Codepen Demo
$(document).ready(function() {
var animationElement = $(".animation");
$("body").on({
mouseover: function() {
animationElement.one('webkitAnimationIteration mozAnimationIteration AnimationIteration', function() {
animationElement.addClass("second-animation");
});
},
mouseleave: function() {
animationElement.one('webkitAnimationIteration mozAnimationIteration AnimationIteration', function() {
animationElement.removeClass("second-animation");
});
}
});
});
Have you used the transition?? If not, please add the transition rules in the parent div.
div{
-webkit-transition: all 500ms linear;
-moz-transition: all 500ms linear;
-ms-transition: all 500ms linear;
-o-transition: all 500ms linear;
transition: all 500ms linear;
}

Resources