Search code examples
sassextend

Two Sass `@extend`s Conflict


I have these lines as part of my navigation sass, simplified here:

// These lines (66-72) should generate what I want.

.top-nav .nav {
  & > ul {
    a {
      @extend %section-button;
    }
  }
}

// These lines (76-82) prevent the previous code from generating what I want. 
// Delete it to see things work.

.nav {
  & > ul {
    a {
      @extend %section-button;
    }
  }
}

When lines 76-82 are deleted, lines 66-72 produce .top-nav .nav > ul a:hover, applying the dark grey color to the text on hover. However, when lines 76-82 are allowed to remain, the .top-nav .nav > ul a:hover selector is not generated. Why is this?

Changing the order of the selector blocks doesn't help.

I need both blocks because in the .nav selector block I override things in %section-button that I don't want to be overridden in .top-nav .nav.

Here's the code in a pen, simplified as much as possible while still demonstrating the problem.

Full code:

HTML:

<div class="top-nav">
  <nav id="nav" class="nav">
    <ul>
      <li class="page-link"> <a href="/live">Live</a></li>
    </ul>
  </nav>
</div>

SCSS:

// Colors
$grey-color-dark:  #3f3f3d;
$grey-color-light: lighten($grey-color-dark, 65%);
$blue: #23527c;
$green: #2d5a3a;

// Section Colors

%section-background-color {
  background: $grey-color-dark;
}

%section-text-color {
  color: $grey-color-dark;
}

// Buttons

%button {
  cursor:pointer;
  padding:0 1rem;
  line-height: 2rem;
  height: 2rem;
  display:inline-block;
}

%section-button {
  @extend %button;
  @extend %section-background-color;
  color:$grey-color-light;

  &:hover, &:focus {
    background: $grey-color-light;
    @extend %section-text-color;
  }
}

// navigation

// These lines (66-72) should generate what I want.

.top-nav .nav {
  & > ul {
    a {
      @extend %section-button;
    }
  }
}

// These lines (76-82) prevent the previous code from generating what I want. Delete it to see things work.

.nav {
  & > ul {
    a {
      @extend %section-button;
    }
  }
}

Solution

  • You're using @extends when you would want to use a mixin. @extends is designed to create groups of classes (and it will compile into one instance), so calling it on both .top-nav .nav and .nav will create a CSS grouping combining both classes and leading to other unwieldiness. Whereas using a mixin will define two different instances of the section-button in the nav and top-nav.

    If you change %section-button to @mixin section-button and the @extend %section-button calls to @include section-button, everything should work.

    If you are set on using placeholders, you'll need to create several placeholders. But I think that kind of defeats the point of using a placeholder. Or if you're not worried about duplicating code, you could just define the CSS you want inside the .top-nav class with a nested :hover, &:focus pseudoselector then whatever color you want.