Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define a dynamic mixin or function name in SASS?

I want to dynamically create mixins in SASS, named after each item in the list, but it doesn't seem to work.

I tried this but I get an error:

$event-icons: fair, concert, art-show, conference, dance-show, film, party, festival, theatre, launch
@each $event-icon in $event-icons
  @mixin event-icon-#{$event-icon}
    background-position: -($event-icon-width * $i) 0

Error:

Invalid CSS after "": expected expression (e.g. 1px, bold), was "#{$event-icon}"

Is this usage not supported by SASS? I couldn't find anything in the manual about it.

like image 331
Cristian Avatar asked Apr 01 '13 18:04

Cristian


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!

How do you define a function in Sass?

Functions are defined using the @function at-rule, which is written @function <name>(<arguments...>) { ... } . A function's name can be any Sass identifier. It can only contain universal statements, as well as the @return at-rule which indicates the value to use as the result of the function call.

How do you define mixin?

Mixins allow you to define styles that can be re-used throughout your stylesheet. They make it easy to avoid using non-semantic classes like . float-left , and to distribute collections of styles in libraries.


3 Answers

Variable interpolation in @mixins does not appear to be supported currently.

The SASS documentation calls this #{} interpolation and describes it like this:

Interpolation: #{}

You can also use SassScript variables in selectors and property names using #{} interpolation syntax:

$name: foo;
$attr: border;
p.#{$name} {
  #{$attr}-color: blue;
}

Per the documentation, interpolation of variable names only appears to be supported for selectors and property names, and not for @mixins. If you'd like that feature, you may want to file an Issue for it, although this one may already be tracking what you're describing.

Edit: Are you sure you need to use a @mixin to accomplish the kind of styling you're talking about? Could you just use a selector with interpolation? For example, would this work:

$event-icons: fair, concert, art-show, conference, dance-show, film, party, festival, theatre, launch
@for $i from 1 to length($event-icons)
  $event-icon: nth($event-icons, $i)
  .event-icon-#{$event-icon}
    background-position: -($event-icon-width * $i) 0
like image 67
Stuart M Avatar answered Sep 24 '22 13:09

Stuart M


As of this moment (March 30th, 2014), Chris Eppstein still refuses to implement dynamic mixins. See issue 857 and issue 626 on Github.

I've been trying to convince Chris that this feature is quite essential for Sass to unleash its true power... and I'm not the only one there.

If you agree that this is an important feature, please go to issue 857 and issue 626 and address this problem yourself. The more of us provide a use case for this feature, the more likely we'll be able to convince Chris and/or one of the other lead developers.


UPDATE: In 2016, Eppstein did end up implementing this feature due to the number of requests for it. However, today (mid 2018), these changes still haven't been merged into the main branch and thus remain unavailable in the sass release. See issue 2057.

like image 21
John Slegers Avatar answered Sep 23 '22 13:09

John Slegers


The best solution is to implement a single mixin that takes an argument.

$event-icons: fair, concert, art-show, conference, dance-show, film, party, festival, theatre, launch
@mixin event-icon($name)
  @if not index($event-icons, $name)
    @error "#{$name} is not an event icon."
  background-position: -($event-icon-width * $i) 0
like image 33
chriseppstein Avatar answered Sep 22 '22 13:09

chriseppstein