just a quick question regarding animated elements in React.js - I have noticed that when trying to make use of the animation-delay property in CSS, that React does not seem to apply this rule at all for some reason.
For example, I am trying to make a basic loading component, which just has a series of basic circles moving about in sequence, the CSS for which is below:
.--loaderContainer {
position: relative;
left: 50%;
top: 50%;
transform: translateX(-50%), translateY(-50%);
width: 4rem;
height: 4rem;
}
.--loaderContainer:nth-child(n) {
width: 1rem;
height: 1rem;
border-radius: 9999px;
margin: 0;
padding: 0;
position: absolute;
animation-name: spin;
animation-duration: 2s;
animation-timing-function: ease;
animation-iteration-count: infinite;
animation-fill-mode: both;
}
.--loaderContainer:first-child {
background-color: red;
transform: rotate(270deg);
animation-delay: -1.5s;
}
.--loaderContainer:nth-child(2) {
background-color: blue;
transform: rotate(180deg);
animation-delay: -1s;
}
.--loaderContainer:nth-child(3) {
background-color: green;
transform: rotate(90deg);
animation-delay: -0.5s;
}
.--loaderContainer:nth-child(4) {
background-color: yellow;
}
#keyframes spin {
0%,
100% {
transform: translate(0);
}
25% {
transform: translate(160%);
}
50% {
transform: translate(160%, 160%);
}
75% {
transform: translate(0, 160%);
}
}
As far as I can tell, this should stagger each of the child elements in sequence, performing the same animation but at different times. However, for some reason, React simply plays the animation, with no delay whatsoever and has all four elements animate at the exact same time.
It seems like a really basic issue to be having and while I have looked up a variety of answers, I just can't seem to find any concrete solutions, so would be super appreciative for any help. Thanks!
If all four circles are seen, I think this animation should be working properly.
The negative animation-delay values ensures that four circles start at different points of the animation, rather than putting an actual delay.
More about animation-delay
Without it, they will start at same point and move together while stacking with each other, resulting in only one circle is seen (the last yellow circle since it's on top of stack).
Here is a basic example for testing the effect of animation-delay by toggling it on and off for all the circles, it can run with the "run code snippet" button below.
Hope it will help.
const btn = document.querySelector("button");
const loaders = document.querySelectorAll(".--loaderContainer");
btn.addEventListener("click", () => {
loaders.forEach((loader) => loader.classList.toggle("no-delay"));
btn.textContent = loaders[0].classList.contains("no-delay")
? "turn delay on"
: "turn delay off";
});
.--loaderContainer {
position: relative;
left: 50%;
top: 50%;
transform: translateX(-50%), translateY(-50%);
width: 4rem;
height: 4rem;
}
.--loaderContainer:nth-child(n) {
width: 1rem;
height: 1rem;
border-radius: 9999px;
margin: 0;
padding: 0;
position: absolute;
animation-name: spin;
animation-duration: 2s;
animation-timing-function: ease;
animation-iteration-count: infinite;
animation-fill-mode: both;
}
.--loaderContainer:first-child {
background-color: red;
transform: rotate(270deg);
animation-delay: -1.5s;
}
.--loaderContainer:nth-child(2) {
background-color: blue;
transform: rotate(180deg);
animation-delay: -1s;
}
.--loaderContainer:nth-child(3) {
background-color: green;
transform: rotate(90deg);
animation-delay: -0.5s;
}
.--loaderContainer:nth-child(4) {
background-color: yellow;
}
#keyframes spin {
0%,
100% {
transform: translate(0);
}
25% {
transform: translate(160%);
}
50% {
transform: translate(160%, 160%);
}
75% {
transform: translate(0, 160%);
}
}
button {
text-transform: uppercase;
padding: 6px;
}
section {
width: 100px;
height: 100px;
position: relative;
}
div.--loaderContainer.no-delay:nth-child(n) {
animation-delay: 0s;
opacity: 0.8;
}
body {
background-color: #aaa;
}
<button>turn delay off</button>
<section>
<div class="--loaderContainer"></div>
<div class="--loaderContainer"></div>
<div class="--loaderContainer"></div>
<div class="--loaderContainer"></div>
</section>
Related
hello I have a text which has fade-in and transform(translate) animation so after the fade-in and transform animation I want a moving text like up and down a lite, not too much in an infinite loop like you are waiting for loading of something
.imgContaner {
width: 100%;
height: 86.6vh;
background-image: url("https://upload.wikimedia.org/wikipedia/commons/8/85/Sky-3.jpg");
background-size: cover;
background-repeat: no-repeat;
position: relative;
overflow: hidden;
}
.imgContaner p {
color: white;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 3em;
text-align: center;
text-shadow: -1px 0 #000000, 1px 0 #000000, 0 1px #000000, 0 -1px #000000;
animation: 4s ease-in-out test ;
opacity: 1;
}
#keyframes test {
from {
transform: translate(-50% , 400%);
opacity: 0;
}
to {
transform: translate(-50%, -50%);
opacity: 1;
}
}
<div className={classes.imgContaner}>
<p>Make Your Dreams Come True</p>
</div>
You can do this in two ways with css.
First way: Add more frames in your #keyframes definition. Instead of using from and to properties, use percentages. For example:
#keyframes test {
0% {
transform: translate(-50% , 400%);
opacity: 0;
}
50% {
transform: translate(-50%, -50%);
opacity: 1;
}
75% {
Do other stuff...
}
100% {
Do other stuff...
}
}
Second way: Chain animations to play after the other one. By adding delay to the second animation equal to the duration of first animation. Like:
animation: test 4s ease-in-out, otherAnim 2s ease-in-out 4s;
Note that you can't do it this way:
animation: test 4s ease-in-out;
animation: otherAnim 2s ease-in-out 4s;
This way first one will be overwriten by second one. Which is not what you want.
I have a 3 chevron animation sequence set up for a back button I designed. The animation triggers on hover exactly the way I want it to but it doesn't respect the ease-out part of the animation property when I hover off of the button. I know that typically with CSS animations you fix this by putting the animation on the actual element and not the :hover state but the problem with that is that the keyframe animation triggers on page load and gets a little wonky on :hover. Is there a mouse-out or hover-out-like state that I could use so that when the user moves away from the button the animation eases out or even reverses? I tried adding animation-direction: reverse; property to the base elements but that doesn't do anything, probably because it doesn't know what animation I'm referring to because it's not present in the base elements for the reasons above. Do I possibly need some CSS or javascript to prevent the animation from triggering until the :hover state actually occurs and then I could place the animation in the base elements instead of the :hover state?
https://jsfiddle.net/astombaugh/L7k1r63f/54/
<body style="background-color: #214365">
<div class="backBtn">
<div class="chevronContainer">
<div class="backBtnChevronTop"></div>
<div class="backBtnChevronMid"></div>
<div class="backBtnChevronFar"></div>
</div>
Back
</div>
</body>
#import url('https://fonts.googleapis.com/css2?family=Oswald:wght#700&display=swap');
.backBtn {
font-family: Oswald, Univers, Helvetica Neue, Helvetica, Arial;
display: inline-block;
position: absolute;
left: 4rem;
font-weight: 700;
width: auto;
height: auto;
color: white;
background-color: transparent;
padding: 0.2rem 0em 0.1rem 0em;
margin: 0rem 0rem 0rem 0rem;
text-align: center;
text-decoration: none;
font-size: 1.6em;
word-spacing: normal;
cursor: pointer;
}
.chevronContainer {
display: inline-block;
position: relative;
transform: translateY(-1.3rem) translateX(-1rem);
}
.backBtnChevronTop {
content: url(https://i.imgur.com/YHZi17i.png);
filter: invert(1);
position: absolute;
opacity: 1;
height: 1.33rem;
width: 1.33rem;
}
.backBtnChevronMid {
content: url(https://i.imgur.com/YHZi17i.png);
filter: invert(1);
position: absolute;
opacity: 0;
height: 1.33rem;
width: 1.33rem;
animation-direction: reverse;
}
.backBtnChevronFar {
content: url(https://i.imgur.com/YHZi17i.png);
filter: invert(1);
position: absolute;
opacity: 0;
height: 1.33rem;
width: 1.33rem;
animation-direction: reverse;
}
.backBtn:hover .backBtnChevronMid {
animation: animateChevronMid 0.6s ease-in-out;
animation-fill-mode: forwards;
}
.backBtn:hover .backBtnChevronFar {
animation: animateChevronFar 0.6s ease-in-out;
animation-fill-mode: forwards;
}
#keyframes animateChevronTop {
0% {
transform: translateX(0rem);
opacity: 0;
}
70%,
100% {
transform: translateX(0);
opacity: 1;
}
}
#keyframes animateChevronMid {
0% {
transform: translateX(0);
opacity: 0;
}
70%,
100% {
transform: translateX(-0.7rem);
opacity: 1;
}
}
#keyframes animateChevronFar {
0% {
transform: translateX(0);
opacity: 0;
}
70%,
100% {
transform: translateX(-1.4rem);
opacity: 1;
}
}
You can probably resolve this by adding the transition on element when there is no hover at the moment and tweak a little the keyframes. Like this:
.backBtn .backBtnChevronMid {
animation: animateChevronMid2 0.6s ease-in-out;
animation-fill-mode: forwards;
}
.backBtn .backBtnChevronFar {
animation: animateChevronFar2 0.6s ease-in-out;
animation-fill-mode: forwards;
}
#keyframes animateChevronMid2 {
0% {
transform: translateX(-0.7rem);
opacity: 1;
}
70%,
100% {
transform: translateX(0);
opacity: 0;
}
}
#keyframes animateChevronFar2 {
0% {
transform: translateX(-1.4rem);
opacity: 1;
}
70%,
100% {
transform: translateX(0);
opacity: 0;
}
}
this additional keyframes are exact opposite of the keyframes that you have done. And they do apply when you move your cursor from the element (so on hover off so to speak).
Jacck is right and beat me to it.
You can use that, and add a fadeIn transition to the back button itself. It's hacky but put this on the back button:
animation: fadeIn 0.6s ease-in-out;
And tweak the animation accordingly. It'll run once. If you don't want a fade just move the "stop" close to the end and this controls the container that holds the other animations so your whole effect won't show until it has loaded:
#keyframes fadeIn {
0% {opacity:0;}
95% {opacity: 0}
100% {opacity:1;}
}
How Can I fix the below code.. I have used the technique of transform:translateY(-50%) to make a div vertically center. But When I use it with animation , it first takes top:50% then it translates giving a jerk.. I don't want the jerk to happen and the element should automatically come in center.
body,
html {
height: 100%;
background: #c9edff;
text-align: center;
}
.element {
position: relative;
top: 50%;
transform: translateY(-50%);
font-family: arial;
font-size: 20px;
line-height: 1.8em;
-webkit-animation-name: zoom;
-webkit-animation-duration: 0.6s;
animation-name: zoom;
animation-duration: 0.6s;
}
#-webkit-keyframes zoom {
from {
-webkit-transform: scale(0);
}
to {
-webkit-transform: scale(1)
}
}
#keyframes zoom {
from {
transform: scale(0)
}
to {
transform: scale(1)
}
}
<div class="element">
Vertical Align is Awesome!
<br /> But with animation its giving a jerk!<br/> Please Fix
</div>
Your animation rule overwrites the translateY(-50%) with scale(), and when the animation is done, the previous rule gets applied again, hence it jumps.
If you add translateY(-50%) to the animation, it will work fine.
A side note, based on whether one put the translateY() before or after the scale(), it animates differently, as transform values gets applied from right to left
body,
html {
height: 100%;
background: #c9edff;
text-align: center;
}
.element {
position: relative;
top: 50%;
transform: translateY(-50%);
font-family: arial;
font-size: 20px;
line-height: 1.8em;
-webkit-animation-name: zoom;
-webkit-animation-duration: 0.6s;
animation-name: zoom;
animation-duration: 0.6s;
}
#-webkit-keyframes zoom {
from {
-webkit-transform: translateY(-50%) scale(0);
}
to {
-webkit-transform: translateY(-50%) scale(1);
}
}
#keyframes zoom {
from {
transform: translateY(-50%) scale(0);
}
to {
transform: translateY(-50%) scale(1);
}
}
<div class="element">
Vertical Align is Awesome!
<br /> But with animation its giving a jerk!<br/> Please Fix
</div>
The problem here ist the line-height, but you can actually use calc to fix that.
transform: translateY(calc(- 50% + 1.8em));
body,
html {
height: 100%;
background: #c9edff;
text-align: center;
}
.element {
position: relative;
top: 50%;
transform: translateY(calc(- 50% + 1.8em));
font-family: arial;
font-size: 20px;
line-height: 1.8em;
-webkit-animation-name: zoom;
-webkit-animation-duration: 0.6s;
animation-name: zoom;
animation-duration: 0.6s;
}
#-webkit-keyframes zoom {
from {
-webkit-transform: scale(0);
}
to {
-webkit-transform: scale(1)
}
}
#keyframes zoom {
from {
transform: scale(0)
}
to {
transform: scale(1)
}
}
<div class="element">
Vertical Align is Awesome!
<br /> But with animation its giving a jerk!<br/> Please Fix
</div>
I have two divs which has one circle along with one smily where innercircle1 div is rotating with given animation.
What i want is when i hover on innercircle1 div it should stop but with their current transform origin position,
Currently when i hover over innercircle1 div it goes to their starting point i.e. their given transform origin and stop.
body {
background: #000;
color: #fff;
}
#keyframes circle {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
#keyframes inner-circle {
from {
transform: rotate(0deg);
}
to {
transform: rotate(-360deg);
}
}
.outercircle {
border: 1px solid red;
border-radius: 50%;
width: 310px;
margin: 64px auto;
height: 310px;
position: Relative;
}
.innercircle {
width: 100px;
height: 100px;
margin: 20px auto 0;
color: orange;
font-size: 100px;
line-height: 1;
animation: circle 5s linear infinite;
transform-origin: 50% 200px;
position: ABSOLUTE;
top: -70px;
left: 109px;
}
.innercircle1 {
animation: inner-circle 5s linear infinite;
}
<div class="outercircle"><div class="innercircle"><div class="innercircle1">☻</div></div></div>
You can pause animation using JQUERY as well as CSS.
A very simple solution to use animation-play-state property.
Try these lines:
.innercircle1 {
animation: inner-circle 5s linear infinite;
animation-play-state: play;
}
.innercircle1:hover{
animation-play-state: paused;
}
I am trying to create a splash screen for my website and I have made a progress bar to make it look nicer. I also have some links for the user to login or register.
What I want to achieve is, right after the window loads, have the progress bar do its thing for 4 seconds then have it fade out in .5 seconds and then have the links fade in in its place in .5s for a total of 5 seconds before the user can proceed.
I have put together some code to make this work using mainly:
setTimeout();
but despite having no errors as far as both I and the Google Chrome console can tell, no visible result is produced.
How can I fix my code to work properly? Any suggestions would be greatly appreciated. I would prefer a solution in plain JavaScript, but if there's no other way, I would be satisfied with a jQuery one too.
To help you, I have assembled a demo for you here.
No doubt to switch to jquery. FadeIn and fadeOut do it easily:
$(window).load(function(){
var t=setTimeout(function(){
$("#progressbar").fadeOut(500);
$("#splashscreen-links").fadeIn(500);
},4000)
})
#-webkit-keyframes greenglow {
from {
left:-120px;
}
to {
left:100%;
}
}
#-moz-keyframes greenglow {
from {
left: -120px;
}
to {
left: 100%;
}
}
#-ms-keyframes greenglow {
from {
left: -120px;
}
to {
left: 100%;
}
}
#-o-keyframes greenglow {
from {
left: -120px;
}
to {
left: 100%;
}
}
#keyframes greenglow {
from {
left: -120px;
}
to {
left: 100%;
}
}
#progressbar {
/* Dimensions */
width: 250px;
height: 16px;
overflow: hidden;
/* Positioning */
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
margin: 5px;
padding-top: 4px;
padding-left: 17px;
/* Styling */
background: #E6E6E6;
border:1px solid #bbb;
border-radius:0px;
}
#progressbar:after {
content: " ";
display: block;
width: 120px;
top: -50%;
height: 250%;
position: absolute;
animation: greenglow 2s linear infinite;
-webkit-animation: greenglow 2s linear infinite;
z-index: 2;
background: #1CAE30;
}
#splashscreen-links {
/* Text */
color: #999999;
font-family: "Arial";
text-decoration: none;
/* Positioning */
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
margin: 5px;
padding-top: 4px;
padding-left: 17px;
/* Visibility */
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="progressbar"></div>
<p id = "splashscreen-links"><a>Login</a> • <a>Register</a></p>
You are already using CSS animations. Just keep going down that path!
#keyframes progresshide {
0% {opacity: 1; display:block; }
80% { opacity: 1; }
100% { opacity: 0; display:none; }
}
#keyframes linksshow {
0% {opacity: 0; }
80% { opacity: 0; }
100% { opacity: 1; }
}
#progressbar {
animation: progresshide 5s linear forwards;
}
#splashscreen-links {
animation: linksshow 5s linear forwards;
}
https://jsfiddle.net/bcwtz8rr/3/
In the case that you'd rather go JS than JQuery, it is still possible using .className to switch the class, setting up classes with transitions of the .5s you mentioned, and using setTimeout appropriately.
First, we start by introducing another two rather simple classes:
.showObject {
transition: all .5s ease-in-out;
-o-transition: all .5s ease-in-out;
-ms-transition: all .5s ease-in-out;
-moz-transition: all .5s ease-in-out;
-webkit-transition: all .5s ease-in-out;
opacity: 1;
}
.hideObject {
transition: all .5s ease-in-out;
-o-transition: all .5s ease-in-out;
-ms-transition: all .5s ease-in-out;
-moz-transition: all .5s ease-in-out;
-webkit-transition: all .5s ease-in-out;
opacity: 0;
}
Then, JS with appropriate setTimeout usage:
window.onload = function SwitchProgress() {
// Declaration
'use strict';
// Fade in
document.getElementById('progressbar').setAttribute('style', 'display: block;');
document.getElementById('progressbar').className = 'showObject';
// Waiting 4s for bar animation, then fading it out
setTimeout(function () {
document.getElementById('progressbar').className = 'HideObject';
// .5s while the bar fades out, removing bar, displaying links
setTimeout(function () {
document.getElementById('progressbar').setAttribute('style', 'display: none;');
document.getElementById('splashscreen-links').setAttribute('style', 'display: block;');
// .01s for display change, links fade in
setTimeout(function () {
document.getElementById('splashscreen-links').className = 'showObject';
}, 10);
}, 990);
}, 4000);
};
Just wanted to note: I got this to work on Codecademy (codebits), which refreshes the file every time you make a change. JSFiddle didn't work as well. Should be fine for usage on a page that's actually going to experience proper onload execution.