Mixin to Qualify a Selector

Avatar of Kitty Giraudel
Kitty Giraudel on (Updated on )

There is no easy way of qualifying a selector from within its associated ruleset. By qualifying I mean prepending an element name (e.g. a) to a class (e.g. .btn) so that a ruleset gets specific to a combination of an element selector and a class selector (e.g. a.btn) for instance.

As of today, the best (and so far only valid way) to do so is as follow:

.button {
  @at-root a#{&} {
    // Specific styles for `a.button`
  }
}

Wow, definitely not really elegant, is it? Ideally, you might want to hide this kind of horrific syntax behind a mixin so that you keep a clean and friendly API, especially if you have rookie developers in your team.

Doing so is extremely simple of course:

/// Since the current way to qualify a class from within its ruleset is quite
/// ugly, here is a mixin providing a friendly API to do so.
/// @author Kitty Giraudel
/// @param {String} $element-selector - Element selector
@mixin qualify($element-selector) {
  @at-root #{$element-selector + &} {
    @content;
  }
}

Now, rewriting our previous snippet:

.button {
  @include qualify(a) {
    // Specific styles for `a.button`
  }
}

Much better, right? Still, qualify can sound a bit tricky for inexperienced Sass tinkerers. You could provide an alias when a more descriptive name, such as when-is.

/// @alias qualify
@mixin when-is($args...) {
  @include qualify($args...) {
    @content;
  }
}

One final example:

.button {
  border: none;
  
  // Qualify `.button` with `button`
  @include qualify(button) {
    -webkit-appearance: none;
  }
  
  // Qualify `.button` with `a`
  @include when-is(a) {
    text-decoration: none;
  }
}