Tableless

Busca Menu

Usando seletores aninhados do SASS com cuidado

Seja o primeiro a comentar por

Não é só por que você está usando um pré-processador que as boas práticas de escrita de CSS devem ser ignoradas. Imagine o código abaixo:

<main class="wrap">
	<div class="content">
		<article>
			<p>Lorem <strong>ipsum dolor sit amet</strong>. Officia rem sed fuga consequatur rerum.</p>
		</article>
	</div>
</main>

E você já deve ter visto um seletor desse tipo:

.wrap .content article p strong {
  color: #ccc;
}

Escrever seletores assim é um tiro no pé. O CSS fica ruim de entender e o trabalho de cascata do CSS – que é o que faz o CSS tão especial – pode se perder, já que você vai precisar fazer um outro seletor, mais específico, para sobreescrever essa formatação caso necessário.

Há outro exemplo mais comum, que é muito visto quando tentamos separar a estrutura e o estilo visual dos elementos. Fica algo assim:

<div class="features">
  <div class="box rounded bordered bg-blue">
    <h1>Título</h1>
    <p>Lorem <strong>ipsum dolor sit amet</strong>. Officia rem sed fuga consequatur rerum.</p>
  </div>
  <div class="box rounded bordered bg-blue">
    <h1>Título</h1>
    <p>Lorem <strong>ipsum dolor sit amet</strong>. Officia rem sed fuga consequatur rerum.</p>
  </div>
  <div class="box rounded bordered bg-blue">
    <h1>Título</h1>
    <p>Lorem <strong>ipsum dolor sit amet</strong>. Officia rem sed fuga consequatur rerum.</p>
  </div>
</div>

É claro que é muito difícil escrever um seletor e um código HTML dessa forma consciente. Você vai perceber que está fazendo alguma burrice e vai pensar duas vezes antes de continuar. Assim espero. Mas quando usamo um pré-processador, é bastante comum nessa armadilha por causa dos seletores aninhados, ou em um termo mais bonito em inglês nested selectors.

Veja um exemplo de nested selector:

.features {
  background-color: #cccccc;
  .box {
    border-radius: 3px;
    border: 1px solid #666666;
    background-color: white;
    p {
      font-size: 1rem;
      line-height: 1.2;
      color: #333333;
    }
  }
}

Coisa linda. Não é necessário repetir o início do seletor a cada elemento que você quer formatar dentro de .features, o SASS fará isso pra você. Veja o output desse código:

.features {
  background-color: #ccc;
}
.features .box {
  border-radius: 3px;
  border: 1px solid #666;
  background-color: white;
}
.features .box p {
  font-size: 1rem;
  line-height: 1.2;
  color: #333;
}

Até aqui tudo gerenciável. Mas suponha que você tenha o código abaixo:

<div class="container">
  <div class="content">
    <div class="features">
      <div class="box rounded bordered bg-blue">
        <h1>Título</h1>
        <p>Lorem <strong>ipsum dolor sit amet</strong>. Officia rem sed fuga consequatur rerum.</p>
      </div>
      <div class="box rounded bordered bg-blue">
        <h1>Título</h1>
        <p>Lorem <strong>ipsum dolor sit amet</strong>. Officia rem sed fuga consequatur rerum.</p>
      </div>
      <div class="box rounded bordered bg-blue">
        <h1>Título</h1>
        <p>Lorem <strong>ipsum dolor sit amet</strong>. Officia rem sed fuga consequatur rerum.</p>
      </div>
    </div>
  </div>
</div>

Aí você faça algo assim usando SASS:

.container {
  max-width: 1200px;
  margin: 0 auto;

  .content {
    padding: 0 20px;

    .features {
      background-color: #ccc;

      .box {
        border-radius: 5px;

        p {
          color: #333;

          strong {
            background-color: #fff;
          }
        }
      }
    }
  }
}

O código final será desse jeito:

.container {
  max-width: 1200px;
  margin: 0 auto;
}

.container .content {
  padding: 0 20px;
}

.container .content .features {
  background-color: #ccc;
}

.container .content .features .box {
  border-radius: 5px;
}

.container .content .features .box p {
  color: #333;
}

.container .content .features .box p strong {
  background-color: #fff;
}

Não é incomum acontecer isso quando você está aprendendo a usar pré-processadores, mas isso pode acontecer facilmente em grandes projetos. Existem muitos problemas ao produzirmos código assim, mas os principais motivos são a geração de código inútil, aumentando o tamanho do seu arquivo final e principalmente a quebra da especificidade e a herança do código CSS. A briga de !important vai acontecer e você vai passar a metade do tempo resolvendo conflitos de formatação. Isso pode sempre ficar pior conforme você aninha cada vez mais os seletores. O segredo aqui é usar no máximo 3 aninhamentos. Há lugares que aconselham até 4 aninhamentos, mas aí eu acho muito. Um código bem feito naturalmente vai ter entre 2 ou 3 aninhamentos. Você não precisa começar a formatar os elementos iniciando seu seletor sempre do elemento pai. No nosso exemplo, tudo ficaria mais higienizado se fizessemos um código assim:

.container {
  max-width: 1200px;
  margin: 0 auto;
}
.content {
  padding: 0 20px;
}

.features {
  background-color: #ccc;

  .box {
    border-radius: 5px;

    p {
      color: #333;

      strong {
        background-color: #fff;
      }
    }
  }
}

O código gerado ficaria assim:

.container {
  max-width: 1200px;
  margin: 0 auto;
}

.content {
  padding: 0 20px;
}

.features {
  background-color: #ccc;
}

.features .box {
  border-radius: 5px;
}

.features .box p {
  color: #333;
}

.features .box p strong {
  background-color: #fff;
}

Dependendo do caso, talvez até daria para tirar o aninhamento de .features. Ficaria assim:

.container {
  max-width: 1200px;
  margin: 0 auto;
}

.content {
  padding: 0 20px;
}

.features {
  background-color: #ccc;
}

.box {
  border-radius: 5px;

  p {
    color: #333;

    strong {
      background-color: #fff;
    }
  }
}

Se você seguir as boas práticas de CSS que já falamos aqui e aqui você estará a salvo.

Sugiro duas ferramentas interessantes para testar códigos SASS. Um deles é o SaasMeister, que converte código SASS em código CSS normal. E o outro é o ScssConverter, que converte código SASS para SCSS.

Publicado no dia