SASS keyframes not compiling as wanted - sass

I am using the following keyframes mixin for SCSS
#mixin keyframes($name) {
#-webkit-keyframes #{$name} {
#content;
}
#-moz-keyframes #{$name} {
#content;
}
#-ms-keyframes #{$name} {
#content;
}
#keyframes #{$name} {
#content;
}
}
it works perfectly, when i have to animate, which has the animation property, but when i try to use it for child elements i get not the output, that i need (but syntax-valid)
Example:
#include keyframes('text') {
0% {
span { color: red; }
}
100% {
span { color: green; }
}
}
Will output (short ouput):
#keyframes text {
0% span { color: red; }
100% span { color: green; }
}
But what i need is:
#keyframes text {
0% {
span { color: red; }
}
100% {
span { color: green; }
}
}
How can i prevent sass from snapping the first brackets?

As far as i am concerned you apply keyframes to an element. so your desired output:
#keyframes text {
0% {
span { color: red; }
}
100% {
span { color: green; }
}
}
does not make much sense in CSS.
I think what you need is something like :
#keyframes span#text {
0% {color: red; }
100% { color: green; }
}
also it is not your mixin problem as this SASS:
0% {
span { color: red; }
}
100% {
span { color: green; }
}
compiles to:
0% span {
color: red; }
100% span {
color: green; }
as desired.
I think the intended usege of your keyframes mixin would be something like:
span#text {
#include keyframes(text) {
0% {
color: red;
}
100% {
color: green;
}
}
}

Related

Condense classes and change properties

I have a donut chart that has 5 states (0 - 5). I'm using it in a Vue application, and the donut chart state changes depending on information.
I've created 5 classes to represent the 5 steps of the chart. Step 0 = 0%, step 1 = 20%, etc. The svg element takes a stroke-dasharray property, this shows how far the chart is filled.
So I created 5 css classes for the steps:
.donut-segment-0 {
animation: donut0 1s;
}
#keyframes donut0{
0% {
stroke-dasharray: 0, 100;
}
100% {
stroke-dasharray: 0, 100;
}
}
.donut-segment-1 {
animation: donut1 1s;
}
#keyframes donut1{
0% {
stroke-dasharray: 0, 100;
}
100% {
stroke-dasharray: 20, 80;
}
}
.donut-segment-2 {
animation: donut2 1s;
}
#keyframes donut2{
0% {
stroke-dasharray: 20, 80;
}
100% {
stroke-dasharray: 40, 60;
}
}
.donut-segment-3 {
animation: donut3 1s;
}
#keyframes donut3{
0% {
stroke-dasharray: 40, 60;
}
100% {
stroke-dasharray: 60, 40;
}
}
.donut-segment-4 {
animation: donut4 1s;
}
#keyframes donut4{
0% {
stroke-dasharray: 60, 40;
}
100% {
stroke-dasharray: 80, 20;
}
}
.donut-segment-5 {
animation: donut5 1s;
}
#keyframes donut5{
0% {
stroke-dasharray: 80, 20;
}
100% {
stroke-dasharray: 100, 00;
}
}
I was wondering if it's possible to condese this a bit. There's a simple logic to it. In each step I change the stroke-daskarray with 20 and call a specific animation.
Took me a bit of time but figured it out:
#for $i from 0 through 5 {
.donut-step-#{$i} {
animation: donut-#{$i} 1s;
}
#keyframes donut-#{$i} {
0% {
stroke-dasharray: ($i - 1) * 20, 100 - (($i - 1) * 20);
}
100% {
stroke-dasharray: $i * 20, 100 - ($i * 20);
}
}
}

animation color sass with variables not working

I want to select the color depend of class. But it always takes the last values in the $color1 and $color2 variables. So it is always showed as yellow.
.animated-color {
-webkit-animation: color_change var(--time-color) infinite alternate;
-moz-animation: color_change var(--time-color) infinite alternate;
-ms-animation: color_change var(--time-color) infinite alternate;
-o-animation: color_change var(--time-color) infinite alternate;
animation: color_change var(--time-color) infinite alternate;
}
.color-white {
$color1: white;
$color2: white;
#-webkit-keyframes color_change {
from {
background-color: $color1;
}
to {
background-color: $color2;
}
}
#-moz-keyframes color_change {
from {
background-color: $color1;
}
to {
background-color: $color2;
}
}
#-ms-keyframes color_change {
from {
background-color: $color1;
}
to {
background-color: $color2;
}
}
#-o-keyframes color_change {
from {
background-color: $color1;
}
to {
background-color: $color2;
}
}
#keyframes color_change {
from {
background-color: $color1;
}
to {
background-color: $color2;
}
}
}
.color-yellow {
$color1: rgb(255, 253, 137);
$color2: rgb(255, 254, 168);
#-webkit-keyframes color_change {
from {
background-color: $color1;
}
to {
background-color: $color2;
}
}
#-moz-keyframes color_change {
from {
background-color: $color1;
}
to {
background-color: $color2;
}
}
#-ms-keyframes color_change {
from {
background-color: $color1;
}
to {
background-color: $color2;
}
}
#-o-keyframes color_change {
from {
background-color: $color1;
}
to {
background-color: $color2;
}
}
#keyframes color_change {
from {
background-color: $color1;
}
to {
background-color: $color2;
}
}
}

How to pass multiple content blocks as arguments to a mixin?

I wanna be able to do something like so:
.myTransitionableElement {
transition: all .5s;
.subChild { transition: all 1s }
#include transitionKeyframes(
start: {
opacity: 0;
transform: tranlsate(50px);
.subChild {
transform: rotate(45deg);
}
},
end: {
opacity: 1;
transform: tranlsate(0);
.subChild {
transform: rotate(0);
}
}
)
}
#mixin transitionKeyframes($args) {
&.transitionStartKeyframe {
#include map_get($args, "start");
}
&.transitionEndKeyframe {
#include map_get($args, "end");
}
}
Which should at the end be equivalent to:
.myTransitionableElement {
transition: all .5s;
.subChild { transition: all 1s }
&.transitionStartKeyframe {
opacity: 0;
transform: tranlsate(50px);
.subChild {
transform: rotate(45deg);
}
}
&.transitionEndKeyframe {
opacity: 1;
transform: tranlsate(0);
.subChild {
transform: rotate(0);
}
}
}
The reason behind this is that I wanna find a way to not have to remember those classes names every time I use a JS abstraction that uses those classes.
You can't pass different content as arguments in SASS mixins.
Below is example of what you can achieve using SASS.
Can you specify what you want to achieve here?
#mixin rtl() {
&.ltr {
#content;
direction: ltr;
}
&.rtl {
#content;
direction: rtl;
}
}
.parent {
#include rtl {
display: flex;
}
}
You can try different approaches here. In this particular one I'm using map to hold the data for me. But if attributes and class names are fixed; you can even simplify it.
$map: (Start: (self: (opacity: '0', transform: 'tranlsate(50px)'), child: (transform: rotate(45deg))), End: (self: (opacity: '1', transform: 'tranlsate(0)'), child: (transform: rotate(0))));
$prefix: transition; $postfix: Keyframe;
#mixin transitionKeyframes($map) {
#each $key, $val in $map {
&.#{$prefix}#{$key}#{$postfix} {
#each $attr, $prop in map-get($val, self) {
#{$attr}: #{$prop};
}
.subChild {
#each $attr, $prop in map-get($val, child) {
#{$attr}: #{$prop};
}
}
}
}
}
.myTransitionableElement {
#include transitionKeyframes($map);
transition: all .5s;
.subChild { transition: all 1s }
}
Use mixins for a repetitive task. Modify the mixin or $frames if you have many variations. Breakdown opacity and transistion further to smaller mixins and invoke them conditionally.
$prefix: transition; $postfix: Keyframe;
$frames: 'Start', 'End';
$opcity-main: ('Start': 0, 'End': 1);
$translate-main: ('Start': 50, 'End': 0);
#mixin transitionKeyframes($frame) {
#each $key in $frame {
&.#{$prefix}#{$key}#{$postfix} {
$opacity: map-get($opcity-main, $key);
$translate: map-get($translate-main, $key);
opacity: $opacity;
transform: tranlsate($translate + px);
}
}
}
.myTransitionableElement {
#include transitionKeyframes($frames);
transition: all .5s;
.subChild { transition: all 1s }
}

Good idea to use #mixin for "DRY'ing" up #keyframes?

Is it a good idea to use mixins to DRY up keyframes as the following example:
Note that I just have left and right here but if I where to have more I think the use of #mixins is a better choice. I am not familiar with the customs of writing neat scss/sass, what is the preferred way?
#keyframes fade-in-left {
0% {
opacity: 0;
transform: translate3d(-100%, 0, 0);
}
100% {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
#keyframes fade-in-right {
0% {
opacity: 0;
transform: translate3d(100%, 0, 0);
}
100% {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
vs
#mixin fade-in-horizontally($direction_value) {
#keyframes fade-in-left {
0% {
opacity: 0;
transform: translate3d($direction_value, 0, 0);
}
100% {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
}
Mixins are great but should not be used just to shorten some code. In that case, you only want to define your #keyframes once.
So, here is a third option: using a list and an each directive.
$keyframes-fade: (
('left', -100%),
('right', 100%)
);
#each $dir, $translateTX in $keyframes-fade {
#keyframes fade-in-#{$dir} {
0% {
opacity: 0;
transform: translate3d($translateTX, 0, 0);
}
100% {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
}
This will make your code shorter while keeping it easy to understand.
You can see the output here

CSS3 - Display an element after a few seconds

I'm using a pure CSS3 AJAX loader animation, however, I'm hoping to modify it a little.
Currently it just spins several balls in a circle, however, I'd like to display a message after about 30 seconds to please continue waiting and after about 60 seconds display another message that things might have failed.
Is it possible to accomplish this with pure CSS3? Or would JavaScript be required to get this done?
this is a pure CSS3 animation effect JSFiddle
.animate {
-webkit-animation: NAME-YOUR-ANIMATION 60s;
-moz-animation: NAME-YOUR-ANIMATION 60s;
-o-animation: NAME-YOUR-ANIMATION 60s;
animation: NAME-YOUR-ANIMATION 60s;
opacity: 0;
}
#keyframes NAME-YOUR-ANIMATION {
0% {
opacity: 0;
}
49% {
opacity: 0;
}
50% {
opacity: 1;
}
99% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#-webkit-keyframes NAME-YOUR-ANIMATION {
0% {
opacity: 0;
}
49% {
opacity: 0;
}
50% {
opacity: 1;
}
99% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#-moz-keyframes NAME-YOUR-ANIMATION {
0% {
opacity: 0;
}
49% {
opacity: 0;
}
50% {
opacity: 1;
}
99% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#-o-keyframes NAME-YOUR-ANIMATION {
0% {
opacity: 0;
}
49% {
opacity: 0;
}
50% {
opacity: 1;
}
99% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#keyframes NAME-YOUR-ANIMATION {
0% {
opacity: 0;
}
49% {
opacity: 0;
}
50% {
opacity: 1;
}
99% {
opacity: 1;
}
100% {
opacity: 0;
}
}
you'll need to do the same for the other message, the vendor css are important if you want it to work for all browsers.
Sources

Resources