CSS animation, is it possible to loop between multiple elements? - css

I want to use the advantage of the css animation ability of doing infinite action to control the child I target each time in a different value THEN at some point go back to the zero and so.
Lets say I want to color the background of a group of 3 DIVs, So the CSS code will be:
<style>
div:nth-of-type(1){
-webkit-animation:coloring 2s infinite;
}
#-webkit-keyframes coloring{
from {background:red;}
to {background:yellow;}
}
<style>
So as long as I used infinite property it will go forever and here I want to increase the value of nth-of-type each time in a row (1,2,3) then when reaching the 3 it will back to 1

Very interesting question. But i don't think CSS support a loop function.
:nth-of-type() can calculate different index but the results will be disabled as one array selection:
:nth-of-type(0,1,2,3). This doesn't support any iteration, all the elements will be selected at once.
This is however possible in javascript/jQuery, as it supports iterations:
var count = 0;
var delay = 0;
$('div').each(function()
{
$('div:eq(' + count +')').delay(delay)
.queue(function()
{
$(this).css('background', 'yellow');
})
count++;
delay += 500;
})
It will iterate every div element. Whith the .eq() selector, every element based on the index value will be selected, this way every element is selected one by one.
Normally this would excecute in seconds, so you wouldn't see the effect of "one-by-one".
I used a delay() to have a delay on the selector, where the delay will be increased at every iteration. In this case after every half second a new .queue() will be added so the each function will not iterate before the queue has been finished.
combined this with the css transition to get the fade-in effect:
transition: background 2s;
-webkit-transition: background 2s; /* Safari */
jsFiddle

Try this:
HTML:
<div class="div active"></div>
<div class="div"></div>
<div class="div"></div>
CSS:
.active {
-webkit-animation:coloring 3s;
}
JS:
var len = $(".div").length;
setTimeout(function () {
change_bg();
},3000);
function change_bg() {
var index = $(".active").index(); // get index of active div
var current;
$(".active").removeClass("active");
if (index == len - 1) { // check if active div is last
current = 0; // if last then start from first
} else {
current = index + 1; // increment otherwise
}
$(".div:eq(" + current + ")").addClass("active"); //change background of next div
setTimeout(function () { //recursive calling
change_bg();
},3000);
}
Fiddle here.

I was reviewing my questions and I wanted to share a different approach to achieve this with pure CSS:
#keyframes coloring {
0% {
background:red;
}
25% {
background:yellow;
}
33% {
background:#ccc;
}
75% {
background:#ccc;
}
100%{
background:#ccc;
}
}
.div {
height:50px;
background:#ccc;
}
.first {
-webkit-animation:coloring 9s ease-out 0s infinite;
animation:coloring 9s ease-out 0s infinite;
-moz-animation:coloring 9s ease-out 0s infinite;
-webkit-animation:coloring 9s ease-out 0s infinite;
}
.second {
-webkit-animation:coloring 9s ease-out 3s infinite;
animation:coloring 9s ease-out 3s infinite;
-moz-animation:coloring 9s ease-out 3s infinite;
-webkit-animation:coloring 9s ease-out 3s infinite;
}
.third {
-webkit-animation:coloring 9s ease-out 6s infinite;
animation:coloring 9s ease-out 6s infinite;
-moz-animation:coloring 9s ease-out 6s infinite;
-webkit-animation:coloring 9s ease-out 6s infinite;
}
<div class="div first"></div>
<div class="div second"></div>
<div class="div third"></div>

Related

Ng enter and leave not working when applied to custom css class

I'm working with ngAnimate to show animations on screen transitions in my angular app. We are using ui-router.
What I want is to have the login screen slide upwards off the screen to reveal the next screen, after the user logs in successfully. How can I apply the .ng-leave class to only the login screen?
Here's the useful code I've got so far:
login-directive.html:
<div class="login-slide" id="login-slide">
<div class="viewport-1">
<header></header>
<background></background>
<login-form callLogin="login(username, password)"></login-form>
<version-footer></version-footer>
</div>
styles.css:
#keyframes slideOutUp {
0% {
transform: translate(0px, 400px);
}
100% {
transform: translate(0, -600px);
}
}
.login-slide.ng-leave {
-webkit-animation: slideOutUp 3s ease;
-moz-animation: slideOutUp 3s ease;
-o-animation: slideOutUp 3s ease;
animation: slideOutUp 3s ease;
}
#login-slide.ng-leave {
-webkit-animation: slideOutUp 3s ease;
-moz-animation: slideOutUp 3s ease;
-o-animation: slideOutUp 3s ease;
animation: slideOutUp 3s ease;
}
From everything I've seen, this should be enough to get the login-slide class to "slide" away when the login is complete because the login screen would be leaving the DOM at that time.
I'm also very open to using a combo of ng-class, ng-if, or any other directives if that would help.
Thanks!
A couple things:
1) You need to use some type of angular directive on the element you're trying to animate. In this case it looks like ng-view would be your best option since you're using ui-router. Here's a good example.
2) .ng-leave is the state of the element at the start of the animation. You need to have its finished state as well: .ng-leave-active. (Also in the example above)
Hope that helps.

What does animation:none do exactly?

I've got an HTML element here with this starting style:
transition: transform 2s;
First, it is animated (it rotatesX) via a class that is added on click. On the next click, another class is added that adds a transform3d that should move the element vertically and this should take 2 seconds as per the rule above.
The transform3d doesn't take effect unless I add this rule to the element: animation: none as well. I am confused on what animation: none actually does. Are there complications with transforming an element that has had an animation applied to it?
animation: none sets all animate-* properties to their initial value:
animation-name: none;
animation-duration: 0s;
animation-timing-function: ease;
animation-delay: 0s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: none;
animation-play-state: running;
The problem is that your element has an animation which affects its transform property. Therefore, when you modify its static transform, you don't see the change because it's overridden by the animation.
Then, if you remove the animation, you see the change in transform.
This is unrelated to transforms, it would happen with any property, like color:
div {
animation: color-anim 1s infinite;
}
#keyframes color-anim {
from { color: red }
to { color: blue }
}
<div>Lorem ipsum</div>
<button onclick="document.querySelector('div').style.color = '#fff'">Make white</button>
<button onclick="document.querySelector('div').style.animation = 'none'">Remove animation</button>

What is the default CSS3 animation timing function?

In the following animation, I haven't specified a timing function, such as linear or ease-in. It seems to default to ease-in, since it slows down once it begins reaching 0%. What is the actual timing function that is being used in this case (or the default)?
#-webkit-keyframes goleft {
0% { left:400px; }
100% { left:0px; }
}
. goleft {
-webkit-animation: goleft 10s infinite;
animation: goleft 10s infinite;
}
The initial value is ease according to the W3 docs on the subject
The CSS3 specification for Animations spells it out simply:
Name: animation-timing-function
Initial: 'ease'

css3 animate pngs with transparency

I have images that I want to swap in and out (no slide effect). The first cycle, the images appear stacked on top of each other (since they have holes). All subsequent cycles, it works correctly (only one visible at a time).
Html
<div class="small xfade">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
css
#keyframes xfade {
0% { opacity:1; }
17% { opacity:1; }
25% { opacity:0; }
92% { opacity:0; }
100% { opacity:1; }
}
.xfade span {
animation-name: xfade;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
animation-duration: 8s;
height: 100%;
left: 0;
/* opacity: 0; */
position: absolute;
top: 0;
width: 100%;
}
All visible at once during first loop
Only one visible during first loop, but flash
An usual scene when doing animations is where you have the same animation for several elements, but you want them to be delayed, making a sort of full cycle.
Then you set a animation-duration of say 8 seconds, and if you have 4 elements, you set a delay of 0 for the first, a delay of 2s for the second, and 4s and 6s for the others.
The problem with this is that the second element only starts animating after 2 seconds. In the meantime, it has the initial properties, that can match, or not, (usually not) the properties of the animation.
The best way to solve that is to realize that, if the animation-duration is 8s, then setting the delay to 2s is the same than setting it to -6s. because if you count 8s starting in -6s, you will end at 2s. But, then the animation is running from the first moment, with the properties that should have.
So, the delays in your case should be 0s, -6s, -4s, -2s. Just subtract the transition-duration from the transition delay.
Whenever you set an animation, and discover than the first animation is wrong, but after that they are ok, the likely problem (and solution) is this.
If you want to make everything go faster, but everything else being the same, then you have to reduce both the animation duration and all the animation delays
Example setting
.xfade span {
animation-duration: 4s;
}
.xfade span:nth-of-type(1) {
animation-delay: -1s;
}
.xfade span:nth-of-type(2) {
animation-delay: -2s;
}
.xfade span:nth-of-type(3) {
animation-delay: -3s;
}
fiddle
Also, let's analyze how the tween time is computed. First of all, you are setting the animation for an element that shares the full time with another 3 elements. That means that every element has 1/4 of the time, that is 25%.
This time has to be divided between time of full display and time of tween. Inthe original example, tween time is 8%. If you want that reduced, let's say that tween time will be 6%. Then, full display time will be 25 - 6 = 19.
That gives us the first part of the keyframes:
#keyframes xfade {
0% { opacity:1; }
19% { opacity:1; }
25% { opacity:0; }
Now, for the final keyframes, we have to remember that the tween time is 6, and set that at the end. The keyframe mus be at 100 - 6 = 94. Remainig keyframes:
94% { opacity:0; }
100% { opacity:1; }
}

Nesting Classes within an ID in the .css?

Okay heres my .css
.centerhex {
background-image:url(http://i.imgur.com/4sZDtfK.png);
height:224px;
width:210px;
position:absolute;
opacity:0;
transition:opacity 2s ease-in-out;
}
.transtart{
opacity:0
}
#-webkit-keyframes fadein {
0%{opacity:0;}
40%{opacity:1;}
50%{opacity:1;}
100%{opacity:0.05;}
}
#keyframes fadein {
0%{opacity:0;}
40%{opacity:1;}
50%{opacity:1;}
100%{opacity:0.05;}
}
.done{
animation-delay:0.5s;
-webkit-animation-delay:0.5s;
}
.fadein{
animation:fadein 0.65s;
animation-timing-function:linear;
animation-fill-mode:forwards;
animation-iteration-count:1;
-webkit-animation-iteration-count:1;
-webkit-animation:fadein 0.65s;
-webkit-animation-timing-function:linear;
-webkit-animation-fill-mode: forwards;
}
#-webkit-keyframes pulse {
0%{opacity:0.05;}
10%{opacity:0.1;}
100%{opacity:0.05;}
}
#keyframes pulse {
0%{opacity:0.05;}
10%{opacity:0.1;}
100%{opacity:0.05;}
}
.pulse{
animation:fadein 4s;
animation-timing-function:linear;
animation-fill-mode:forwards;
animation-iteration-count:infinite;
animation-delay:1s
-webkit-animation-delay:1s;
-webkit-animation-iteration-count:infinite;
-webkit-animation:fadein 4s;
-webkit-animation-timing-function:linear;
-webkit-animation-fill-mode: forwards;
}
What I was curious about is if it is possible to create an id specifically for nesting predefined classes, such as:
#hexa.centerhex.transtart.fadein.done
So far experiments in doing this have failed.. so Im not entirely sure what Im doing wrong.
The idea I have for this is that Im going to be creating some script that replaces an ID with another ID. For instance I would make:
#hexa.centerhex.transtart.fadein.done
Turn into:
#hexb.centerhex.transtart.pulse.done
You can do what you're asking but it seems like you're hoping for an unrealistic result based on the ordering of your classes that you typed out. The rendering won't go in a certain order based on selectors you choose unfortunately.
However, this can be done with Javascript fairly easily using a setTimeout() if timing was an issue.
And if you don't care about the order of operations on these classes being added to each id, then you should be able to do this as much as you want (and with reasonably high success as the #id is only trumped by !important and client-side/browser settings).
Don't forget your semicolons :)

Resources