@scope — Estilos Verdadeiramente Isolados no CSS

Como a regra @scope permite limitar seletores CSS a uma parte específica do HTML, criando componentes com estilos isolados sem depender de BEM, CSS Modules ou Shadow DOM.

Isolar estilos a um pedaço específico do HTML sempre dependeu de convenções como BEM, de CSS Modules ou de ferramentas de build. A regra @scope traz esse isolamento para o CSS nativo: ela define um limite superior e, opcionalmente, um limite inferior, e as regras dentro dela só afetam o que está dentro desse "donut" de escopo.

O problema que o @scope resolve

Sem escopo, um seletor genérico como .card p vaza para qualquer p dentro de qualquer .card na página, inclusive cards aninhados uns dentro dos outros ou variações de componente que não deveriam ser afetadas:

.card p {
    color: #444;
}

/* Se um .card estiver dentro de outro .card, essa regra
   também atinge o parágrafo do card interno */

Como funciona

A sintaxe básica usa @scope com um seletor entre parênteses definindo a raiz do escopo. Dentro do bloco, & representa essa raiz:

@scope (.card) {
    :scope {
        border: 1px solid #ddd;
        padding: 16px;
    }

    p {
        color: #444;
    }

    a {
        color: #12A8C3;
    }
}

Aqui, p e a só recebem o estilo quando estão dentro de um elemento .card, mas continuam sendo seletores curtos e simples de escrever.

Limite inferior com "to"

O ponto mais interessante do @scope é poder definir também um limite inferior, criando um escopo em formato de "rosquinha" (donut scope) que exclui uma subárvore específica:

@scope (.card) to (.card-conteudo-externo) {
    p {
        color: #444;
    }
}
<div class="card">
    <p>Este parágrafo recebe o estilo.</p>

    <div class="card-conteudo-externo">
        <p>Este parágrafo NÃO recebe, pois está além do limite.</p>
    </div>
</div>

Isso é útil para evitar que os estilos de um componente "vazem" para conteúdo injetado dinamicamente ou para componentes de terceiros renderizados dentro dele.

Prioridade por proximidade

Quando dois blocos @scope diferentes tentam estilizar o mesmo elemento, vence o escopo cuja raiz está mais próxima do elemento na árvore do DOM, e não a ordem em que as regras foram escritas no arquivo CSS:

@scope (.tema-claro) {
    .botao {
        background: #fff;
        color: #111;
    }
}

@scope (.card) {
    .botao {
        background: #12A8C3;
        color: #fff;
    }
}

Se um .botao estiver dentro de .card, que por sua vez está dentro de .tema-claro, vence o estilo do .card por estar mais próximo do botão, independente da ordem no arquivo.

Quando usar

Cuidados

O @scope não substitui Shadow DOM: ele isola seletores, mas não isola herança de propriedades nem impede que estilos globais (como os aplicados no body ou em *) continuem afetando os elementos dentro do escopo.

Compatibilidade

O @scope alcançou Baseline em 2025, com suporte em todas as versões atuais do Chrome, Edge, Safari e Firefox. Para projetos que ainda precisam suportar navegadores mais antigos, vale envolver o uso em um @supports (selector(&)) ou aguardar mais um pouco antes de adotar em produção.

caniuse

Conclusão

O @scope resolve um problema antigo do CSS — a falta de isolamento real entre componentes — sem exigir pré-processadores, convenções de nomenclatura ou Shadow DOM. É uma peça a mais para escrever CSS mais previsível e fácil de manter em projetos grandes.

Tecnologia:
css

Deixe seu Comentário!

Comentário
Nome
Email