How to define a dynamic mixin or function name in

2019-01-18 21:55发布

问题:

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.

回答1:

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


回答2:

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.



回答3:

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