@scope regra finalmente dá aos desenvolvedores a confiança para escrever CSS que possa acompanhar os front-ends modernos?
Ao aprender os princípios básicos do CSS, aprendemos a escrever estilos modulares, reutilizáveis e descritivos para garantir a manutenção. Mas quando os desenvolvedores se envolvem com aplicativos do mundo real, muitas vezes parece impossível adicionar recursos de UI sem que os estilos vazem para áreas não intencionais.
Esse problema muitas vezes se transforma em uma bola de neve que se transforma em um ciclo auto-realizável; estilos que teoricamente têm como escopo um elemento ou classe começam a aparecer onde não pertencem. Isso força o desenvolvedor a criar seletores ainda mais específicos para substituir os estilos vazados, que então substituem acidentalmente os estilos globais e assim por diante.
Convenções rígidas de nomes de classes, como BEM, são uma solução teórica para esse problema. O Metodologia BEM (Bloco, Elemento, Modificador) é uma forma sistemática de nomear classes CSS para garantir a capacidade de reutilização e a estrutura dos arquivos CSS. Convenções de nomenclatura como essa podem reduzir a carga cognitiva aproveitando a linguagem de domínio para descrever elementos e seu estado e, se implementadas corretamente, podem facilitar a manutenção de estilos para aplicativos grandes.
No mundo real, porém, nem sempre funciona assim. As prioridades podem mudar e, com a mudança, a implementação torna-se inconsistente. Pequenas alterações na estrutura HTML podem exigir muitas revisões de nomes de classes CSS. Com aplicativos front-end altamente interativos, os nomes de classes que seguem o padrão BEM podem se tornar longos e difíceis de manejar (por exemplo, app-user-overview__status--is-authenticating), e não aderir totalmente às regras de nomenclatura quebra a estrutura do sistema, anulando assim os seus benefícios.
Dados esses desafios, não é de admirar que os desenvolvedores tenham recorrido a frameworks, sendo o Tailwind o framework CSS mais popular. Em vez de tentar travar o que parece ser uma guerra invencível de especificidade entre estilos, é mais fácil desistir do CSS Cascade e usar ferramentas que garantam isolamento completo.
Os desenvolvedores confiam mais nos utilitários
Como sabemos que alguns desenvolvedores desejam evitar estilos em cascata? É a ascensão de ferramentas front-end “modernas” – como estruturas CSS-in-JS – projetadas especificamente para esse propósito. Trabalhar com estilos isolados com escopo restrito a componentes específicos pode parecer uma lufada de ar fresco. Ele elimina a necessidade de nomear as coisas – ainda uma das tarefas de front-end mais odiadas e demoradas – e permite que os desenvolvedores sejam produtivos sem compreender totalmente ou aproveitar os benefícios da herança CSS.
Mas abandonar o CSS Cascade traz seus próprios problemas. Por exemplo, compor estilos em JavaScript requer configurações de construção pesadas e muitas vezes leva a estilos que se misturam de maneira estranha com marcação de componente ou HTML. Em vez de convenções de nomenclatura cuidadosamente consideradas, permitimos que ferramentas de construção gerem automaticamente seletores e identificadores para nós (por exemplo, .jsx-3130221066), exigindo que os desenvolvedores acompanhem outra pseudolinguagem por si só. (Como se a carga cognitiva de entender o que todos os seus componentes useEffecto que já não foi suficiente!)
Abstrair ainda mais o trabalho de nomear classes para ferramentas significa que a depuração básica geralmente fica restrita a versões específicas de aplicativos compiladas para desenvolvimento, em vez de aproveitar recursos nativos do navegador que suportam depuração em tempo real, como ferramentas de desenvolvedor.
Felizmente, os recursos CSS modernos não apenas tornam a escrita de CSS padrão mais flexível, mas também dão a desenvolvedores como nós muito mais poder para gerenciar a cascata e fazê-la funcionar para nós. CSS Cascade Layers são um ótimo exemplo, mas há outro recurso que recebe uma surpreendente falta de atenção – embora isso esteja mudando agora que recentemente se tornou Compatível com linha de base.
O CSS @scope Regra
Eu considero o CSS @scope regra ser uma cura potencial para o tipo de ansiedade induzida por vazamento de estilo que abordamos, uma cura que não nos força a comprometer as vantagens nativas da web em troca de abstrações e ferramentas extras de construção.
“O
@scopeA regra CSS permite que você selecione elementos em subárvores DOM específicas, direcionando elementos com precisão, sem escrever seletores excessivamente específicos que são difíceis de substituir e sem acoplar seus seletores com muita força à estrutura DOM.-MDN
Em outras palavras, podemos trabalhar com estilos isolados em instâncias específicas sem sacrificar a herança, a cascata ou mesmo a separação básica de interesses esse tem sido um princípio orientador de longa data do desenvolvimento front-end.
Além disso, possui excelente cobertura do navegador. Na verdade, o Firefox 146 adicionou suporte para @scope em dezembro, tornando-o compatível com o Baseline pela primeira vez. Aqui está uma comparação simples entre um botão usando o padrão BEM e o @scope regra:
O @scope regra permite precisão com menos complexidade. O desenvolvedor não precisa mais criar limites usando nomes de classes, o que, por sua vez, permite escrever seletores baseados em elementos HTML nativos, eliminando assim a necessidade de padrões prescritivos de nomes de classes CSS. Simplesmente eliminando a necessidade de gerenciamento de nomes de classes, @scope pode aliviar o medo associado ao CSS em grandes projetos.
Uso Básico
Para começar, adicione o @scope regra em seu CSS e insira um seletor raiz para o qual os estilos terão escopo:
@scope () {
/* Styles scoped to the */
}
Então, por exemplo, se tivéssemos que definir o escopo dos estilos para um
@scope (nav) {
a { /* Link styles within nav scope */ }
a:active { /* Active link styles */ }
a:active::before { /* Active link with pseudo-element for extra styling */ }
@media (max-width: 768px) {
a { /* Responsive adjustments */ }
}
}
Isso, por si só, não é um recurso inovador. No entanto, um segundo argumento pode ser adicionado ao escopo para criar um limite inferiordefinindo efetivamente os pontos inicial e final do escopo.
/* Any `a` element inside `ul` will not have the styles applied */
@scope (nav) to (ul) {
a {
font-size: 14px;
}
}
Essa prática é chamada escopo de rosquinhae há diversas abordagens que podem ser usadas, incluindo uma série de seletores similares e altamente específicos acoplados firmemente à estrutura do DOM, um :not pseudo-seletor ou atribuir nomes de classes específicos a elementos dentro do
Independentemente dessas outras abordagens, o @scope método é muito mais conciso. Mais importante ainda, evita o risco de estilos quebrados se os nomes das classes mudarem ou forem mal utilizados ou se a estrutura HTML for modificada. Agora isso @scope é compatível com o Baseline, não precisamos mais de soluções alternativas!
Podemos levar essa ideia adiante com vários limites finais para criar um “estilo figura oito”:
Compare isso com uma versão tratada sem o @scope regra, onde o desenvolvedor deve “redefinir” os estilos para seus padrões:
main a {
font-size: 14px;
}
main p {
line-height: 16px;
color: darkgrey;
}
main aside a,
main nav a {
font-size: inherit; /* or whatever the default should be */
}
main aside p,
main nav p {
line-height: inherit; /* or whatever the default should be */
color: inherit; /* or a specific color */
}
Confira o exemplo a seguir. Você percebe como é simples direcionar alguns seletores aninhados e isentar outros?
Veja a caneta [@scope example [forked]](https://codepen.io/smashingmag/pen/wBWXggN) por Blake Lundquist.
Considere um cenário em que estilos exclusivos precisam ser aplicados ao conteúdo com slots em componentes da web. Ao inserir conteúdo em um componente da web, esse conteúdo se torna parte do Shadow DOM, mas ainda herda estilos do documento pai. O desenvolvedor pode querer implementar estilos diferentes dependendo de qual componente da web o conteúdo está inserido:
Jane Doe
Jane Doe
Neste exemplo, o desenvolvedor pode querer que o ter estilos distintos apenas se for renderizado dentro :
@scope (team-roster) {
user-card {
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
user-card img {
border-radius: 50%;
width: 40px;
height: 40px;
}
}
Mais benefícios
Existem maneiras adicionais que @scope pode eliminar a necessidade de gerenciamento de classes sem recorrer a utilitários ou nomes de classes gerados por JavaScript. Por exemplo, @scope abre a possibilidade de facilmente alvo descendentes de qualquer seletornão apenas nomes de classes:
/* Only div elements with a direct child button are included in the root scope */
@scope (div:has(> button)) {
p {
font-size: 14px;
}
}
E eles pode ser aninhadocriando escopos dentro de escopos:
@scope (main) {
p {
font-size: 16px;
color: black;
}
@scope (section) {
p {
font-size: 14px;
color: blue;
}
@scope (.highlight) {
p {
background-color: yellow;
font-weight: bold;
}
}
}
}
Além disso, o escopo raiz pode ser facilmente referenciado no @scope regra:
/* Applies to elements inside direct child `section` elements of `main`, but stops at any direct `aside` that is a direct chiled of those sections */
@scope (main > section) to (:scope > aside) {
p {
background-color: lightblue;
color: blue;
}
/* Applies to ul elements that are immediate siblings of root scope */
:scope + ul {
list-style: none;
}
}
O @scope at-rule também introduz um novo proximidade dimensão para resolução de especificidade CSS. No CSS tradicional, quando dois seletores correspondem ao mesmo elemento, o seletor com maior especificidade vence. Com @scopequando dois elementos têm especificidade igual, vence aquele cuja raiz do escopo estiver mais próxima do elemento correspondente. Isso elimina a necessidade de substituir os estilos principais aumentando manualmente a especificidade de um elemento, uma vez que os componentes internos substituem naturalmente os estilos dos elementos externos.
Conclusão
Frameworks CSS utilitários, como Tailwind, funcionam bem para prototipagem e projetos menores. Seus benefícios diminuem rapidamente, entretanto, quando usados em projetos maiores que envolvem mais do que alguns desenvolvedores.
O desenvolvimento front-end tornou-se cada vez mais complicado nos últimos anos, e o CSS não é exceção. Enquanto o @scope regra não é uma panacéia, ela pode reduzir a necessidade de ferramentas complexas. Quando usado no lugar ou junto com a nomenclatura de classe estratégica, @scope pode tornar mais fácil e divertido escrever CSS sustentável.

