I'm trying to call a mixin using a variable as the name, like so:
@include $mixin-name;
That doesn't seem so difficult...
I've seen a few people online mention wanting to do this. This ticket (http://dev.vaadin.com/ticket/9546) says "fixed", which I assumed meant that in Sass 3.2 it was possible, but this comment from the Sass group on Google Groups seems to suggest otherwise: http://goo.gl/HtdHu
I see what they're saying, it seems many people who are asking about it could quite easily solve their issues another way.
I can't think of another way for my issue though, so let me explain and maybe someone might have an idea or two?
CSS Animation
I've created a mixin for @keyframes
so that I can call @include animation();
and get the full list of prefixed and official @keyframes
@include keyframes(reveal) {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
Gives me:
@-webkit-keyframes reveal {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@-moz-keyframes reveal {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@-ms-keyframes reveal {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@-o-keyframes reveal {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes reveal {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
Which is great! But if I use Compass transform
in one of the keyframe states:
@include keyframes(round) {
from {
@include transform(rotateZ(-145deg));
opacity: 1;
}
to {
@include transform(rotateZ(-45deg));
opacity: 0.5;
}
}
then I end up getting something like:
@-webkit-keyframes round {
from {
-webkit-transform: rotateZ(-145deg);
-moz-transform: rotateZ(-145deg);
-ms-transform: rotateZ(-145deg);
-o-transform: rotateZ(-145deg);
transform: rotateZ(-145deg);
opacity: 1;
}
to {
-webkit-transform: rotateZ(-45deg);
-moz-transform: rotateZ(-45deg);
-ms-transform: rotateZ(-45deg);
-o-transform: rotateZ(-45deg);
transform: rotateZ(-45deg);
opacity: 0.5;
}
}
etc...
Prefixes inside prefixes
So, I know that this is pedantic, but it's really annoying me that I am declaring -webkit-animation
, but then inside I have to declare all of the prefixes when what I want to do is only declare the same prefix as the keyframes and the official, eg:
@-webkit-keyframes round {
from {
-webkit-transform: rotateZ(-145deg);
transform: rotateZ(-145deg);
opacity: 1;
}
to {
-webkit-transform: rotateZ(-45deg);
transform: rotateZ(-45deg);
opacity: 0.5;
}
}
@-moz-keyframes round {
from {
-moz-transform: rotateZ(-145deg);
transform: rotateZ(-145deg);
opacity: 1;
}
to {
-moz-transform: rotateZ(-45deg);
transform: rotateZ(-45deg);
opacity: 0.5;
}
}
etc...
Mixin problems
So, I've created a mixin using @include experimental-value
, but I can't automate it enough because
@function browser-is-prefix($browser, $prefix) {
@if $browser == $prefix {
@return true;
} @else {
@return false;
}
}
@mixin transform-prefix($transform, $browser) {
@include experimental-value(transform, $transform,
browser-is-prefix($browser, -moz),
browser-is-prefix($browser, -webkit),
browser-is-prefix($browser, -o),
browser-is-prefix($browser, -ms),
false, true);
}
@mixin animation-name($browser) {
from {
@include transform-prefix(transform(translate(-25px,200px) scale(0.5)), $browser);
opacity: 0;
}
to {
@include transform-prefix(transform(translate(0,0) scale(0.5)), $browser);
opacity: 1;
}
}
Calling @include animation-name(-webkit)
will work great and give us:
@-webkit-keyframes animation-name {
from {
-webkit-transform: translate(-25px,200px) scale(0.5);
transform: translate(-25px,200px) scale(0.5);
opacity: 0;
}
to {
-webkit-transform: translate(0,0) scale(0.5);
transform: translate(0,0) scale(0.5);
opacity: 1;
}
}
But I can't automate it!
To automate the process I wanted to be able to call a mixin, something like @include prekeyframes(animation-name);
and have prekeyframes
do exactly what the keyframes
mixin does above, except instead of blindly including the @content
of the, it will include the mixin and only use the prefixes it should based on what prefix the @keyframes has:
@mixin prekeyframes($name) {
$prefixes : -webkit-, -moz-, -o-, -ms-, '';
@each $prefix in $prefixes {
@include $name($prefix);
}
}
This, of course, throws an error. If I interpolate $name
(@include #{$name}($prefix)
), it's still an issue.
So, I could just live with the extra transform
values, or I could do it all manually, but I've always been really impressed with the flexibility of Sass and this seems really limiting to me...
To summarise:
- I want to define the animation once, in one place.
- I want to be able to
@include transform
within that animation. - I want the correctly prefixed
transform
inside the correctly prefixed@keyframes
I've spent a few hours on this now, and I'll continue to fiddle... But if anyone has similar experiences or problems, I'd love to know...
Thanks!