Herança no Sass

  1. Casos simples
  2. Múltiplas extensões
  3. Seletores criados apenas para extensão
  4. Extensões em diretivas

Casos simples

A herança é uma das melhores funcionalidades do Sass. Ela deixa seus estilos muito mais simples de se escrever e deixa a marcação mais limpa também. Ela é feita usando a diretiva @extend:

.button {
  color: white;
  border: 2px solid black;
}

.small-button {
  @extend .button;
  font-size: 0.7em;
  padding: 0.2em;
}

.medium-button {
  @extend .button;
  font-size: 1em;
  padding: 0.4em;
}
.button, .small-button, .medium-button {
  color: white;
  border: 2px solid black; }

.small-button {
  font-size: 0.7em;
  padding: 0.2em; }

.medium-button {
  font-size: 1em;
  padding: 0.4em; }

Observe como o seletor .button tem suas características herdadas facilmente. Com CSS puro, geralmente nessa situação o .medium-button não herda as características do .button. Ele só define as suas próprias características. Por isso, um botão médio do HTML precisa usar as duas classes (.button e .medium-button). Usando a herança do Sass, só é preciso colocar a classe .medium-button. Isso deixa a marcação mais limpa.

É importante entender que não é a regra que é estendida, mas sim o seletor. Assim, as regras onde o seletor estendido é usado afetam os seletores que o estendem também. Exemplo:

.button {
  color: white;
  border: 2px solid black;
}

.cta .button {
  color: red;
}

.small-button {
  @extend .button;
  font-size: 0.7em;
  padding: 0.2em;
}

.medium-button {
  @extend .button;
  font-size: 1em;
  padding: 0.4em;
}
.button, .small-button, .medium-button {
  color: white;
  border: 2px solid black; }

.cta .button, .cta .small-button, .cta .medium-button {
  color: red; }

.small-button {
  font-size: 0.7em;
  padding: 0.2em; }

.medium-button {
  font-size: 1em;
  padding: 0.4em; }

Múltiplas extensões

Também dá pra fazer várias extensões, separando os seletores estendidos por vírgula:

.button {
  color: white;
  border: 2px solid black;
}

.alert-button {
  @extend .button;
  color: red;
}

.small-button {
  @extend .button;
  font-size: 0.7em;
  padding: 0.2em;
}

.small-alert-button {
  @extend .small-button, .alert-button;
}
.button, .alert-button, .small-alert-button, .small-button {
  color: white;
  border: 2px solid black; }

.alert-button, .small-alert-button {
  color: red; }

.small-button, .small-alert-button {
  font-size: 0.7em;
  padding: 0.2em; }

Só não dá pra estender combinators (como div > .bar).

Seletores criados apenas para extensão

Se você cria um seletor que apenas é estendido e nunca é usado diretamente, você pode usar um placeholder selector. Esse tipo de seletor não é escrito quando está sozinho, porque se supõe que ele foi feito só para extensão, e não para uso direto. Para criar um, é só seguir a sintaxe %seletor. Exemplo:

%error {
  font: Arial;
  padding: 2em;
}

.user-error {
  @extend %error;
  color: yellow;
}

.critical-error {
  @extend %error;
  color: red;
}
.user-error, .critical-error {
  font: Arial;
  padding: 2em; }

.user-error {
  color: yellow; }

.critical-error {
  color: red; }

Extensões em diretivas

Extensões em diretivas só podem estender seletores que estão dentro do bloco da diretiva. Exemplo:

@media screen and (min-width: 768px) {
  .button {
    color: white;
    border: 2px solid black;
  }

  .alert-button {
    @extend .button;
    color: red;
  }
}
@media screen and (min-width: 768px) {
  .button, .alert-button {
    color: white;
    border: 2px solid black; }

  .alert-button {
    color: red; } }

Se o seletor .button estivesse fora da diretiva @media, um erro iria acontecer.