Herança no SASS
Este artigo explica a herança no SASS.
Vamos explicar a herança no SASS com exemplos práticos.
YouTube Video
Herança no SASS
A herança no SASS (@extend) é um mecanismo que permite aplicar os estilos de um seletor em outro sem duplicação. Como os mesmos estilos são 'combinados' e aplicados a vários elementos na marcação, o CSS resultante tende a ser menos redundante; porém, se usado de forma inadequada, pode levar à mescla indesejada de seletores.
Noções básicas: Como usar o @extend
Abaixo está um exemplo básico onde .btn--primary herda os estilos de .btn. @extend é uma diretiva que estende o seletor de destino.
1// Base button styles
2.btn {
3 padding: 0.5rem 1rem;
4 border-radius: 4px;
5 border: 1px solid #ccc;
6 background: white;
7 color: #333;
8}
9
10/* Primary button extends the base .btn */
11.btn--primary {
12 @extend .btn;
13 background: #007bff;
14 color: white;
15}- Ao usar
@extend,.btn--primaryherda os estilos base de.btne sobrescreve apenas as partes necessárias.
CSS Gerado
1.btn, .btn--primary {
2 padding: 0.5rem 1rem;
3 border-radius: 4px;
4 border: 1px solid #ccc;
5 background: white;
6 color: #333;
7}
8
9.btn--primary {
10 background: #007bff;
11 color: white;
12}Melhor Prática: Utilizando Placeholders (%placeholder)
Seletores de espaço reservado (%name) são seletores que não são gerados no CSS. Eles são amplamente utilizados, especialmente quando você deseja compartilhar estilos comuns de forma segura, exclusivamente para herança entre vários componentes.
1// %placeholder will not be output directly
2%card-base {
3 padding: 1rem;
4 border-radius: 6px;
5 box-shadow: 0 1px 3px rgba(0,0,0,0.08);
6 background: #fff;
7}
8
9/* Components extend the placeholder */
10.card {
11 @extend %card-base;
12 border: 1px solid #eee;
13}
14
15.panel {
16 @extend %card-base;
17 border: 1px solid #ddd;
18}.carde.panelambos herdam de%card-base, permitindo compartilhar estilos comuns enquanto adicionam diferenças conforme necessário.
CSS Gerado
1.card, .panel {
2 padding: 1rem;
3 border-radius: 6px;
4 box-shadow: 0 1px 3px rgba(0,0,0,0.08);
5 background: #fff;
6}
7
8.card {
9 border: 1px solid #eee;
10}
11
12.panel {
13 border: 1px solid #ddd;
14}Herança múltipla (Vários @extend)
Você pode herdar vários placeholders ou classes ao mesmo tempo. Embora a reutilização de estilos seja melhorada, é importante acompanhar quais regras estão combinadas com quais seletores.
1%btn-base {
2 display: inline-block;
3 padding: 0.5rem 1rem;
4 border-radius: 3px;
5}
6
7%btn-large {
8 padding: 0.75rem 1.5rem;
9 font-size: 1.125rem;
10}
11
12/* Composite button that extends both placeholders */
13.btn--lg {
14 @extend %btn-base;
15 @extend %btn-large;
16 background: #222;
17 color: #fff;
18}- Este é um exemplo onde um botão herda dois placeholders, um para 'base' e outro para 'tamanho'.
.btn--lgherda tanto%btn-basequanto%btn-large, combinando o layout básico com o tamanho maior.
CSS Gerado
1.btn--lg {
2 display: inline-block;
3 /* %btn-large overrides the padding from %btn-base */
4 padding: 0.75rem 1.5rem;
5 border-radius: 3px;
6 font-size: 1.125rem;
7 background: #222;
8 color: #fff;
9}Comportamento do @extend (Mecanismo de Mesclagem) e cuidados com 'explosão de seletores'
@extend gera todos os seletores compatíveis mesclados juntos, o que pode às vezes resultar em combinações indesejadas de seletores.
O exemplo a seguir mostra como a saída pode aumentar quando a mesma classe base é estendida em vários lugares.
1/* Many components extend .utility */
2/* A generic utility class */
3.utility {
4 margin-bottom: 1rem;
5}
6
7/* Nested selectors that extend .utility */
8.header {
9 @extend .utility;
10 .title {
11 font-weight: bold;
12 }
13}
14
15.footer {
16 @extend .utility;
17 .note {
18 color: #888;
19 }
20}
21
22.article {
23 @extend .utility;
24 .content {
25 line-height: 1.6;
26 }
27}
28
29.sidebar {
30 @extend .utility;
31 .section {
32 padding: 1rem;
33 }
34}- Quando vários componentes herdam
.utility, os seletores são mesclados em um só e, em projetos de grande escala, isso pode causar inchaço do CSS.
CSS Gerado
1.utility,
2.header,
3.footer,
4.article,
5.sidebar {
6 margin-bottom: 1rem;
7}
8
9.header .title {
10 font-weight: bold;
11}
12
13.footer .note {
14 color: #888;
15}
16
17.article .content {
18 line-height: 1.6;
19}
20
21.sidebar .section {
22 padding: 1rem;
23}@extend e .class vs seletores de elementos (tags) — prioridade e efeitos colaterais
@extend pode ser aplicado não apenas a classes, mas também a seletores de elementos. No entanto, estender elementos aumenta o escopo afetado, elevando o risco de as regras serem aplicadas involuntariamente em locais não desejados.
Abaixo está um exemplo de extensão de um seletor de elemento e o efeito que isso pode causar.
1/* Extending an element selector (not recommended) */
2h1 {
3 font-size: 2rem;
4 margin-bottom: 0.5rem;
5}
6
7/* If you extend h1, the resulting selector will include your class with h1 */
8.title {
9 @extend h1;
10 color: #333;
11}
12
13/* Output becomes:
14h1, .title { font-size: 2rem; margin-bottom: 0.5rem; }
15*/- Neste exemplo, ao herdar o seletor de elemento
h1,.titleserá mesclado com os mesmos estilos deh1. - Embora possa parecer conveniente em casos de pequena escala, à medida que seu projeto cresce, regras para
h1podem se combinar inesperadamente com.title, tornando os estilos mais complexos e reduzindo a manutenção. Portanto, projetar estilos principalmente em torno de classes e espaços reservados torna-os mais fáceis de manter.
CSS Gerado
1h1,
2.title {
3 font-size: 2rem;
4 margin-bottom: 0.5rem;
5}
6
7.title {
8 color: #333;
9}Casos de uso para @extend e !optional
Se você especificar !optional com @extend, pode suprimir erros caso o alvo de herança não exista. Isso é especialmente útil em códigos do tipo biblioteca ou em casos onde os espaços reservados são definidos condicionalmente.
A seguir, um exemplo de como tentar herdar com segurança uma classe que pode não existir, utilizando !optional.
1/* Try to extend a class that might not exist */
2.component {
3 @extend .maybe-existing !optional;
4 padding: 1rem;
5}- Se
.maybe-existingnão existir, nada acontecerá e a herança será ignorada. Você pode usar isso quando quiser tentar uma extensão de forma segura.
CSS Gerado
1.component {
2 padding: 1rem;
3}Comparação entre @extend e mixins (@mixin / @include)
@extend e @mixin às vezes têm propósitos semelhantes, mas seus resultados e casos de uso diferem.
-
@extend- O CSS gerado reduz redundância ao mesclar seletores.
- Como os seletores são mesclados após a geração, combinações indesejadas podem ocorrer.
- Parâmetros não podem ser passados (embora isso possa ser compensado combinando placeholders).
-
@mixin/@include- Cada chamada duplica os estilos (causando saída redundante).
- Você pode passar parâmetros e incluir lógica como condicionais ou laços.
- A saída é mais previsível, mas o tamanho do arquivo aumenta.
Abaixo está uma comparação usando tanto @mixin quanto @extend para implementar os mesmos estilos de botão.
1/* Mixin approach */
2@mixin btn-styles($bg, $color) {
3 display: inline-block;
4 padding: 0.5rem 1rem;
5 background: $bg;
6 color: $color;
7 border-radius: 4px;
8}
9
10/* Use mixin */
11.btn {
12 @include btn-styles(white, #333);
13}
14
15.btn--primary {
16 @include btn-styles(#007bff, white);
17}
18
19/* Extend approach (shared placeholder) */
20%btn-base {
21 display: inline-block;
22 padding: 0.5rem 1rem;
23 border-radius: 4px;
24}
25
26.btn2 {
27 @extend %btn-base;
28 background: white;
29 color: #333;
30}
31
32.btn2--primary {
33 @extend %btn-base;
34 background: #007bff;
35 color: white;
36}@mixinpermite inserir estilos de forma flexível, enquanto@extendconsolida a saída de maneira eficiente, assim você pode usar cada um conforme o caso de uso.
CSS Gerado
Saída de @mixin
1.btn {
2 display: inline-block;
3 padding: 0.5rem 1rem;
4 background: white;
5 color: #333;
6 border-radius: 4px;
7}
8
9.btn--primary {
10 display: inline-block;
11 padding: 0.5rem 1rem;
12 background: #007bff;
13 color: white;
14 border-radius: 4px;
15}Saída de @extend
1.btn2,
2.btn2--primary {
3 display: inline-block;
4 padding: 0.5rem 1rem;
5 border-radius: 4px;
6}
7
8.btn2 {
9 background: white;
10 color: #333;
11}
12
13.btn2--primary {
14 background: #007bff;
15 color: white;
16}Orientações práticas
A herança no SASS é um recurso poderoso para aumentar a reutilização de estilos. No entanto, o uso incorreto pode tornar a mesclagem de estilos complexa e reduzir a manutenção. Abaixo estão alguns pontos-chave para usar herança de forma segura e eficiente.
- Use espaços reservados para estilos puramente comuns de componentes, como estrutura e layout. Além disso, se a parametrização dinâmica for necessária, você pode usar
@mixin. - Você deve evitar herdar diretamente elementos HTML como
h1. Combinações de seletores não intencionais podem ocorrer, podendo resultar na geração de CSS inesperado. - Utilizar convenções de nomes como BEM ou prefixos claros para indicar o propósito de cada placeholder ajuda a manter a segurança.
- É mais seguro usar
@extenddentro do mesmo arquivo. Especialmente em projetos grandes, é recomendável projetar a herança dentro do escopo de cada componente para facilitar o acompanhamento das relações de herança.
Resumo
O recurso @extend no SASS é uma maneira conveniente de reutilizar estilos comuns de forma eficiente e garantir a consistência do design. No entanto, como as combinações de seletores podem facilmente se tornar complexas, é necessário usar esse recurso com cuidado e em um escopo limitado. Agrupando estilos compartilhados com seletores de espaço reservado (%placeholder) e usando @mixin para partes que exigem parâmetros dinâmicos, você pode manter um design simples e de fácil manutenção.
Você pode acompanhar o artigo acima usando o Visual Studio Code em nosso canal do YouTube. Por favor, confira também o canal do YouTube.