Search code examples
csssasscss-selectorsampersand

Using a list of selectors in combination with & in a nested selector in Sass SCSS


In a Sass sheet I'm working on, I'd like to be able to store some body classes inside of a variable, and use them in a selector nested inside of a selector for some elements, like this:

$classes: ".bodyClass1, .bodyClass2";

.aClass, .anotherClass {
  /* some styles */
  #{$classes} & {
    /* Styles under $classes */
  }
  #{$classes} &:hover {
    /* Styles under $classes when hovering */
  }
}

The output I'm looking for is:

.aClass, .anotherClass {
  /* some styles */
}
.bodyClass1 .aClass, .bodyClass2 .aClass, .bodyClass1 .anotherClass, .bodyClass2 .anotherClass {
  /* Styles under $classes */
}
.bodyClass1 .aClass:hover, .bodyClass2 .aClass:hover, .bodyClass1 .anotherClass:hover, .bodyClass2 .anotherClass:hover {
  /* Styles under $classes when hovering */
}

But it renders as:

.aClass, .anotherClass {
  /* some styles */
}
.aClass .bodyClass1, .bodyClass2 .aClass, .anotherClass .bodyClass1, .bodyClass2 .anotherClass {
  /* Styles under $classes */
}
.aClass .bodyClass1, .bodyClass2 .aClass:hover, .anotherClass .bodyClass1, .bodyClass2 .anotherClass:hover {
  /* Styles under $classes when hovering */
}

I can fix this by creating separate variables with &, &:hover, &:active, etc. after the body classes instead, but I'm wondering if there's a way to use variables in the way I was trying to use them.

Edit:

srekoble's solution to use loops works perfectly for me! I adapted it into a function, here it is if anyone else might want to use it:

$classes: ".bodyClass1", ".bodyClass2";

@function c($classes, $append: null){
  $processedClasses: "";

  $length: length($classes);

  @for $i from 1 through $length {
    @if $append {
      $processedClasses: #{$processedClasses}#{nth($classes, $i)} #{$append}#{", "};
    } @else {
      $processedClasses:  #{$processedClasses}#{nth($classes, $i)}#{", "};
    }
  }

  @return $processedClasses;
}

.aClass, .anotherClass {
  /* some styles */

  #{c($classes, "&")} {
    /* Styles under $classes */
  }
  #{c($classes, "&:hover")} {
    /* Styles under $classes when hovering */
  }
}

Which outputs as:

.aClass, .anotherClass {
  /* some styles */
}
.bodyClass1 .aClass, .bodyClass2 .aClass, .bodyClass1 .anotherClass, .bodyClass2 .anotherClass {
  /* Styles under $classes */
}
.bodyClass1 .aClass:hover, .bodyClass2 .aClass:hover, .bodyClass1 .anotherClass:hover, .bodyClass2 .anotherClass:hover {
  /* Styles under $classes when hovering */
}

Solution

  • You could try something like this:

    $classes: ".bodyClass1" , ".bodyClass2";
    
    .aClass, .anotherClass {
      /* some styles */
      @for $i from 1 through 2 {
        #{nth($classes, $i)} & {
          /* Styles under $classes */
        }
    
        #{nth($classes, $i)} &:hover {
          /* Styles under $classes when hovering */
        }
      }
    }
    

    An example: http://sassmeister.com/gist/acb0096e9d35e1ae437d