Rey
Rey

Reputation: 3767

Sass: Multiple class selector from a variable

I want to create a variable with classes like so

$multi: foo, bar, baz

And I want to created a combined selector like so:

.foo, .bar, .baz {}

I am used the indented syntax (don't know if that would matter). The reason I want the combined selector generated from the variable: I need to do calculations based on how many classes are defined there. Please don't give a suggestion like (use extends!) because that will require me to make another class. I need to be able to get close or exactly to the regular combined selector output.

Upvotes: 5

Views: 3593

Answers (3)

Andrew Patton
Andrew Patton

Reputation: 5404

I had the same issue as the OP, and this was the first search result I found, so now that I’ve figured it out, I’ll post my solution, even though the question is 1.5 years old.

Here’s what I found out: in order to use a variable as a selector, you use SASS interpolation, which works perfectly with comma-separated strings. However, if you want the variable that holds your selectors to be a list (so that you can use list functions on it, e.g. length($multi)), the interpolation will generate a malformed selector.

So, the simple solution is to first define your variable as a list, then when you need to use it as a selector, convert that list into a comma-separated string:

$multi: ".foo", ".bar", ".baz"
$multi-selector: ""
@each $selector in $multi
    @if $multi-selector != ""
        $multi-selector: $multi-selector + ", "
    $multi-selector: $multi-selector + $selector

#{$multi-selector}
    //CSS properties go here

You may want to abstract the list-to-comma-separated-string functionality into a function (note: SASS’s join function doesn’t do this; it joins two lists into a new one). Here’s one possible implementation:

@function unite($list, $glue: ", ")
    @if length($list) == 1
        @return $list

    $string: ""
    @each $item in $list
        @if $string != ""
            $string: $string + $glue
        $string: $string + $item
    @return $string

At which point the original code can be as concise as:

$multi: ".foo", ".bar", ".baz"

#{unite($multi)}
    //CSS properties go here

Upvotes: 4

Able
Able

Reputation: 366

(code from previous answer) Cool function! Usefull. I just wanted to add some SCSS syntax, to give an opportunity to people to use it:

@function unite($list, $glue: ", ") {
     @if length($list) == 1 {
             @return $list;
     } @else {
        $string: "";
        @each $item in $list {
             @if $string != "" { $string: $string + $glue; }
                 $string: $string + $item;
     }

     @return $string;
     }
}

At which point the original code can be as concise as:

$multi: ".foo", ".bar", ".baz"

#{unite($multi)}
    //CSS properties go here

Upvotes: 1

maxbeatty
maxbeatty

Reputation: 9325

Compass offers a built-in sprite mixin that does just this. If you don't want to use all of Compass, you could look into their source to see how they are doing it.

Upvotes: 0

Related Questions