Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Including mixins using variables for name in Sass

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!

like image 431
Trolleymusic Avatar asked Mar 05 '13 17:03

Trolleymusic


People also ask

How do you define mixin in sass?

Defining a MixinA mixin is defined with the @mixin directive. Tip: A tip on hyphens and underscore in Sass: Hyphens and underscores are considered to be the same. This means that @mixin important-text { } and @mixin important_text { } are considered as the same mixin!

Is a mixin a variable?

Mixin do some kind of styling which can be used again again in your whole styling and same you can use variable as much as you can. Functions and Mixins are different. One returns value while the other is used like a macro to substitute.

Which directive is used to include the mixin in the code in sass?

@mixin directive is used to define the mixin. @include directive is used to include the mixins in the document. The SassScript values can be taken as arguments in mixins, which is given when mixin is included and available as variable within the mixin. Block of styles are passed to the mixin.

Which arguments are used to include arguments in the mixins?

Keyword arguments: The arguments are used to include in mixins. These types of arguments, if named, can be passed in any order and their default values can be skipped.


1 Answers

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

like image 119
fregante Avatar answered Nov 16 '22 03:11

fregante