Sass use variables to set animation property - css

I have an animation that gets applied to all the .wave children of an element:
.waves > .wave {
animation: wave 0.5s 2 alternate;
}
And I am using a Sass for loop to cycle through all of the waves and apply a property, say, animation-delay.
#for $i from 1 to 31 {
.wave:nth-child(#{$i}) {
animation-delay: 0.5s * $i;
}
}
I want to set a variable using $i that gets used in the keyframes.
#for $i from 1 to 31 {
.wave:nth-child(#{$i}) {
$max: 0.8 * $i;
}
}
#keyframes wave {
from {
transform: scaleY(0);
}
to {
transform: scaleY($max);
}
}

Related

Is it possible to reassign or increment/decrement a variable in SASS?

I have setup a style-rule using SASS to animate some elements in my application.
It was originally setup like this (where $dropdown-length is 1.5s):
&:nth-child(2) {
animation-delay: ($dropdown-length + 0.2s);
}
&:nth-child(3) {
animation-delay: ($dropdown-length + 0.4s);
}
&:nth-child(4) {
animation-delay: ($dropdown-length + 0.6s);
}
&:nth-child(5) {
animation-delay: ($dropdown-length + 0.8s);
}
&:nth-child(6) {
animation-delay: ($dropdown-length + 1s);
}
&:nth-child(7) {
animation-delay: ($dropdown-length + 1.2s);
}
&:nth-child(8) {
animation-delay: ($dropdown-length + 1.4s);
}
&:nth-child(9) {
animation-delay: ($dropdown-length + 1.6s);
}
As you can see, this is very repetitive and not very DRY. So I attempted to use the benefits of SASS. I came up with:
#for $num from 2 through 10 {
$i: 0;
&:nth-child(#{$num}) {
$i: $i + 0.2s;
animation-delay: ($dropdown-length + $i);
}
}
However, I am struggling to find if it is possible to increment another variable (in this example $i) on each iteration in the for loop. At the moment, it seems to just set $i to 0.2s and stays constant at 0.2s for each iteration. I would like for $i to increment by 0.2s for each successive iteration. Any ideas? Thanks.
As #Justinas says, your loop resets itself every iteration. You should take $i out of the loop, something like this:
$dropdown-length: 1.5s;
.foo {
$i: 0;
#for $num from 2 through 10 {
&:nth-child(#{$num}) {
$i: $i + 0.2s;
animation-delay: ($dropdown-length + $i);
}
}
}
Which outputs:
.foo:nth-child(2) {
animation-delay: 1.7s;
}
.foo:nth-child(3) {
animation-delay: 1.9s;
}
.foo:nth-child(4) {
animation-delay: 2.1s;
}
.foo:nth-child(5) {
animation-delay: 2.3s;
}
.foo:nth-child(6) {
animation-delay: 2.5s;
}
.foo:nth-child(7) {
animation-delay: 2.7s;
}
.foo:nth-child(8) {
animation-delay: 2.9s;
}
.foo:nth-child(9) {
animation-delay: 3.1s;
}
.foo:nth-child(10) {
animation-delay: 3.3s;
}

delaying an animation for x seconds with css

I have an element I would like to fade in and fade out but show for 10 seconds.
.element {
-webkit-animation: fadeinout 2s linear forwards;
transition-delay: 10s;
animation: fadeinout 2s linear forwards;
opacity: 0;
}
#-webkit-keyframes fadeinout {
50% { opacity: 1; }
}
#keyframes fadeinout {
50% { opacity: 1; }
}
I have been trying for a while and think I have completely miss understood something.
UPDATE -----
What I'm trying to do is for the element to fade in over 2 seconds then show for 10 secs then fade out over 2 seconds.
transition-delay is wrong. It is about the transition. The equivalent of that is: animation-delay. use animation-duration: 14s for the time of running animation. or:
.element {
-webkit-animation: fadeinout 14s linear forwards;
animation: fadeinout 14s linear forwards;
opacity: 0;
width: 100px;
height: 100px;
background-color: red;
}
#-webkit-keyframes fadeinout {
14% { opacity: 1; }
86% { opacity: 1; }
100% { opacity: 0; }
}
#keyframes fadeinout {
14% { opacity: 1; }
86% { opacity: 1; }
100% { opacity: 0; }
}
<div class="element"></div>
This may be a little verbose, but if it is acceptable for your fade duration to be proportional to the duration it is shown you could use a keyframe structure like this:
#keyframes fadeinout {
0% { opacity: 0; },
10% { opacity: 1; },
90% { opacity: 1; },
100% { opacity: 0; }
}
To get a 2 second fadein, a 'stay there' for 10 seconds and then a 2 second fadeout you have an overall animation time of 14 seconds.
For the first (2 / 14) * 100% [=14.29%] you want the opacity to go from 0 to 1
For the next (10 / 14) * 100% [=71.43%] you want the opacity to stay at 1
For the last (2 / 14) * 100% [=14.29%] you want the opacity to go from 1 to 0.
So the animation keyframes look like this:
#keyframes fadeinout {
0%, 100% { opacity: 0; }
14.29%, 85.72% { opacity: 1; }
}
You don't want a delay on your animation (animation-delay just delays the start of an animation).
Current CSS does not allow us to use a calc function in the % settings in keyframes so we've had to do the calculation in advance and build it in (it didn't seem worth going to more than a couple of decimal places).
.element {
animation: fadeinout 14s linear forwards;
opacity: 0;
width: 20vmin;
height: 20vmin;
background-color: magenta;
}
#keyframes fadeinout {
0%,
100% {
opacity: 0;
}
14.29%,
85.72% {
opacity: 1;
}
}
<div class="element"></div>

Reverse a list of items in sass using #for loop

This is my #for loop in sass:
#for $i from 1 through 10 {
#users[data-state='unload'] li:nth-child(#{$i}n) {
animation-delay: #{$i * 0.1}s;
}
}
Which generates this css:
#users[data-state=loaded] li:nth-child(1n) {
animation-delay: 0.1s;
}
#users[data-state=loaded] li:nth-child(2n) {
animation-delay: 0.2s;
}
#users[data-state=loaded] li:nth-child(3n) {
animation-delay: 0.3s;
}
/// etc...
what i want to do is have my css read as:
#users[data-state=loaded] li:nth-child(1n) {
animation-delay: 1s;
}
#users[data-state=loaded] li:nth-child(2n) {
animation-delay: 0.9s;
}
#users[data-state=loaded] li:nth-child(3n) {
animation-delay: 0.8s;
}
/// etc....
So I am wondering what is the math calculation needed to reverse the animation delay so that the last child element has the shortlist time and the first child element the longest?
many thanks
W9914420
Change animation-delay: #{$i * 0.1}s; as animation-delay: #{(10 - $i) * 0.1}s;
#for $i from 0 through 10 {
#users[data-state='unload'] li:nth-child(#{$i}n) {
animation-delay: #{(10 - $i) * 0.1}s;
}
}

How to use SCSS/SASS to increase animation-delay for concurrent divs

I am trying to replicate the loading animation of the Windows 8 tiles. It seems that each tile has an animation delay which is slightly higher than its predecessor. I have been acheiving this currently by using nth-child in an inefficient way as you can see below. Does anyone know a way that I can achieve this in a more efficient manner that would cater for any number of divs?
DEMO
.results div:nth-child(1) {
animation-delay: 0.25s;
}
.results div:nth-child(2) {
animation-delay: 0.5s;
}
.results div:nth-child(3) {
animation-delay: 0.75s;
}
.results div:nth-child(4) {
animation-delay: 1s;
}
.results div:nth-child(5) {
animation-delay: 1.25s;
}
.results div:nth-child(6) {
animation-delay: 1.5s;
}
.results div:nth-child(7) {
animation-delay: 1.75s;
}
.results div:nth-child(8) {
animation-delay: 2s;
}
You can use a for loop in Sass to do this like so:
#for $i from 1 to 10 {
.results div:nth-child(#{$i}) { animation-delay: $i * 0.25s; }
}
Then you can do it for any number of divs by making the 10 to what ever you need.
#for $i from 1 through 10 {
.results div:nth-child(#{$i}) {
-webkit-animation-delay:(#{$i*0.1s});
animation-delay:(#{$i*0.1s});
}
}
Better solution... I tested and it works ;)
I use this mixin:
#mixin delay($rule, $number, $value) {
#for $i from 1 to ($number + 1) {
&:nth-child(#{$i}) {
-webkit-#{$rule}-delay: (#{$i*$value});
#{$rule}-delay: (#{$i*$value});
}
}
}
.results div{
#include delay(animation, 8, 0.25s);
}
This way you can re use it transitions too.

Can delayed animation attributes override existing ones?

Situation
The DOM element initial state is opacity: 0.
I'm adding animation class to a DOM element. Aside of the animation, this class has an initial state of opacity: 1.
.animation {
opacity: 1;
animation(fadeIn 1s 200ms ease-in-out);
}
The animation is executed with a delay of 200ms, and has an initial state of opacity: 0.
#keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
Problem
When the animation class gets apended to the DOM element, the element becomes instantly visible for 200ms, after which, the fadeIn animation begins by flickering the DOM element back to invisible state. Contrary to this, I would like for the animation (keyframes) attribute opacity:0 to overwrite the animation class attribute opacity:1 and as a result have a smooth fadeIn animation.
Reason for this approach is older-browser support.
EDIT: Added the actual project code ( for clarification purposes )
#for $i from 1 through 3 {
&.showAddonColumn#{$i} {
td:nth-child( #{$i + 1} ) {
display: table-cell;
}
#for $j from 1 through 15 {
tr:nth-child( #{$j} ) {
td {
.checkable {
#include transform-origin(50%, 0%);
#include animation(leafShow 1s #{$j*100ms} cubic-bezier(.37,0,.16,.94) 1);
#include animation-fill-mode(forwards);
}
}
}
}
}
}
You could manually delay the animation itself:
#keyframes fadeIn {
0% { opacity: 0; }
17% { opacity: 0; }
100% { opacity: 1; }
}
and extend the animation:
animation: fadeIn 1200ms ease-in-out;

Resources