7
votes

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!

1
This sounds more like a feature request for Sass/Compass, than an actual question.cimmanon
It's a question, a conundrum, and a topic of discussion. I can see from what was said on the links that it was a request that was denied for some reason. I thought it was interesting and wanted to know if anyone else had any input.Trolleymusic
SO is not a discussion forum. It's clear that you've exhausted all possible options available to you as the Sass project currently stands. The only option that is left is to solicit the developers with a good use case as to why it should be added/changed.cimmanon
Ok, thanks? I'll do that. And maybe someone else will have the same issue and find this post relevant.Trolleymusic
In fact, they're acting on a feature request already: github.com/nex3/sass/issues/626Trolleymusic

1 Answers

2
votes

Check out Bourbon (relevant code and documentation), it's fantastic.