Here is a mixin for situations where you want to combine both animation and keyframes properties. First we need to separate these actions into 2 mixin so we can easily understand the combination of them.
To create an animation mixin we need to pass into an argument the animation value. We shouldn't forget although the prefixes If we don't use an automated task/gem like autoprefixer. So let's first start with the prefix mixin which is responsible for the automate injection of the needed prefixes.
So the prefix mixin will be the following:
@mixin prefix($property, $value) {
$vendors: (webkit moz ms o);
@each $vendor in $vendors {
#{"-" + $vendor + "-" + $property}: #{$value};
}
#{$property}: #{$value};
}
The above mixin has 2 arguments the $property which can be any property with a prefix like tranform, animation or transition and the $value argument which store the property value.
Now that we have the prefix mixin we can easily output the animation prefixes.
// If we include like this:
div {
@include prefix(animation, fadein 1s linear);
}
// The output will be:
div {
-webkit-animation: fadein 2s linear;
-moz-animation: fadein 2s linear;
-ms-animation: fadein 2s linear;
-o-animation: fadein 2s linear;
animation: fadein 2s linear;
}
We can easily use the above solution for any other property with prefixes like transition or transform.
Our keyframes mixin contain only 1 argument, the keyframes $name. Since keyframe have different syntax from animation we can't use the above prefix mixin so we chose the verbose way. Because we need to set the mixin value as the keyframes name we need to use the interpolation method to pass the value as a string.
@mixin keyframes($name) {
@-webkit-keyframes #{$name} {
@content;
}
@-moz-keyframes #{$name} {
@content;
}
@-o-keyframes #{$name} {
@content;
}
@keyframes #{$name} {
@content;
}
}
// If we include like this:
@include keyframes(fadein) {
0% { opacity: 0; }
100% { opacity: 1; }
}
// The output will be:
@-webkit-keyframes fadein {
0% { opacity: 0; }
100% { opacity: 1; }
}
@-moz-keyframes fadein {
0% { opacity: 0; }
100% { opacity: 1; }
}
@-o-keyframes fadein {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes fadein {
0% { opacity: 0; }
100% { opacity: 1; }
}
If we're using an automated task like autoprefixer again the above mixin is redundant.
Now that we explained how these mixins work individually let's combine them to create the ultimate solution.
Our animation mixin now contain the keyframes. So our arguments are the animation value and the keyframes name. Of course the @at-root is needed so keyframes can be extracted outside of the element in which mixin is included.
@mixin animation($name, $value) {
@include prefix(animation, $value);
@at-root {
@-webkit-keyframes $name {
@content;
}
@-moz-keyframes $name {
@content;
}
@-o-keyframes $name {
@content;
}
@keyframes $name {
@content;
}
}
}
// If we include like this:
div {
@include animation(fadein, fadein 2s linear) {
0% { opacity: 0; }
100% { opacity: 1; }
}
}
// The output will be:
div {
-webkit-animation: fadein 2s linear;
-moz-animation: fadein 2s linear;
-ms-animation: fadein 2s linear;
-o-animation: fadein 2s linear;
animation: fadein 2s linear;
}
@-webkit-keyframes fadein {
0% { opacity: 0; }
100% { opacity: 1; }
}
@-moz-keyframes fadein {
0% { opacity: 0; }
100% { opacity: 1; }
}
@-o-keyframes fadein {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes fadein {
0% { opacity: 0; }
100% { opacity: 1; }
}
Quite easy ha! Now we can set our animation without care about keyframes or prefixes.
You can see the above mixin in action in the following gist, enjoy!
Tweet