Search code examples
csssasscompass-sass

The Sass ampersand and attribute selectors


I want to create a sass file that the selectors will be attribute selectors.

When I work with class selectors, in most of the cases I will do

.parent {
    &-child {
    }
}

which gives me the following css: .parent-child {}.

I want to achieve the same thing with attribute selectors:

[data-parent] {
    &-child {
    }
}

which I want to become: [data-parent-child] {}

someone knows how to achieve this? thanks.


Solution

  • You can use this mixin as a workaround to get the desired result.

    @mixin child-attribute($child) {
      $string: inspect(&);
      $original: str-slice($string, 3, -4);
      @at-root #{ selector-replace(&, &, "[#{$original}#{$child}]" ) } {
        @content;
      }
    }
    

    The code simply does the following

    1. $string variable is responsible for turning the parent selector to a string using the inspect function
    2. $original variable is responsible for getting the text content of the $string variable i.e the value 'data-parent' from '([data-parent])'
    3. selector-replace function then replaces the parent selector with the concatenation of the $original variable and child variable

    When used in the following ways

    [data-parent] {
      @include child-attribute('-child') {
        color: green;
      }
    }
    

    The css output

    [data-parent-child] {
      color: green;
    }
    

    Depending on what you want to achieve, it can also be used like this

    [grandparent] {
      @include child-attribute('-parent') {
        color: white;
        @include child-attribute('-child') {
          color: blue;
        }
      }
    }
    

    Which generates the following css

    [grandparent-parent] {
      color: white;
    }
    
    [grandparent-parent-child] {
      color: blue;
    }
    

    Hope this helps you