<
Menu

Tableless



Scoped CSS

Scoped CSS é um novo recurso do HTML5 nos permite definir estilos que serão aplicados apenas em um determinado escopo de marcação.

Scoped CSS é uma pequena novidade no HTML5 que nos permite inserir estilos CSS que sejam apenas aplicado em um determinado lugar de uma página, de modo que os estilos restantes da mesma página não sejam afetados. Para isso, foi definido um novo atributo scoped que deve ser utilizado na tag <style>.

Pela definição da especificação:

O atributo scoped é um atributo booleano. Se for setado, indica que os estilos (da tag <style>) serão aplicados apenas na sub-árvore do elemento pai deste mesmo elemento (<style>), ao contrário de todo o documento.
— WHATWG

Antes de tudo

Se você quiser testar os exemplos mostrados neste post no browser, terá que usar o Google Chrome versão 20 ou superior, pois é o único que já dá suporte a scoped CSS. Com seu Chrome aberto, digite na barra de endereços: chrome://flags. Vai abrir a tela de configurações das flags do Chrome, procure por Enable <style scoped>, e ative a opção (se já não estiver ativada). Agora o reinicie e é só mandar ver.

Show me the money code

Para entendermos melhor, vamos a parte boa, nerds! No trecho de HTML abaixo, temos um cenário bem simples: 2 parágrafos soltos e 2 parágrafos agrupados em uma <div>. Dentro da <div> há também um elemento <style> que define a cor vermelha para os parágrafos (<p>):

<p>I was crowned with a spike right thru my head.</p>
<p>But it's all right now, in fact, it's a gas!</p>
<div>
    <style>
        p { color: red } /* parágrafos vermelhos */
    </style>
    <p>But it's all right, Im jumpin jack flash,</p>
    <p>Its a gas! gas! gas!</p>
</div>

OK, do jeito como está no código acima, o navegador aplicará os estilos de <style> em toda a página, ou seja, todos os parágrafos (<p>) serão da cor vermelha:

I was crowned with a spike right thru my head.
But it’s all right now, in fact, it’s a gas!

But it’s all right, Im jumpin jack flash,
Its a gas! gas! gas!

Aplicando o atributo scoped em <style>, os estilos apenas serão aplicados ao mesmo escopo, ou seja, nos dois últimos parágrafos:

<p>I was crowned with a spike right thru my head.</p>
<p>But it's all right now, in fact, it's a gas!</p>
<div>
    <!-- aplicando atributo scoped -->
    <style scoped>
        p { color: red }
    </style>
    <p>But it's all right, Im jumpin jack flash,</p>
    <p>Its a gas! gas! gas!</p>
</div>

E o resultado será:

I was crowned with a spike right thru my head.
But it’s all right now, in fact, it’s a gas!

But it’s all right, Im jumpin jack flash,
Its a gas! gas! gas!

Grande coisa…

É isso que você deve estar pensando agora. “Grande coisa, não precisamos disso, apenas podemos definir uma classe ou id e estilizá-los like the old times“. Eu concordo que devemos utilizar determinadas soluções apenas quando for realmente necessário, eu mesmo não sairia por ai inserindo estilos <style scoped> em tudo quanto é lugar. Iria ser uma zona.

O pulo do gato

Algumas aplicações podem acrescentar elementos <style> programaticamente a uma página. Nestes casos, há o perigo de que as novas regras afetem o conteúdo da página de forma não intencional. Ao utilizar o atributo scoped, as aplicações podem impedir que este infeliz efeito colateral aconteça.

Sendo assim, utilizar scoped em estilos pode ser uma solução elegante para a componentização de aplicações web de terceiros. Hoje em dia (quase) todo mundo faz uso de plugins de widgets e de diversos tipos em suas aplicações, e muita gente faz mashups com várias dessas aplicações, misturando tudo em uma única solução. Isto não é nenhuma novidade – há muito tempo.

Então, o que acontece? Sabendo que muitas pessoas reutilizarão um determinado plugin, são usados diversos nomes de classes CSS de uma maneira a evitar conflitos com os estilos de outros sites – onde farão uso desses plugins.

Um ótimo exemplo é o Disqus. Para usar o Disqus, apenas precisamos inserir um pequeno script na nossa página, e ele cuidará de todo o resto. Ao visitar uma página que utiliza o Discus, esse script incluirá as marcações necessárias para os comentários já inseridos e seu formulário, além de seus estilos CSS, imagens, e até mesmo outros scripts. Ou seja, é um exemplo completo de aplicação de terceiros rodando em sites do mundo inteiro. Agora, se formos analisar os códigos HTML que são inseridos, teremos nomes de classes CSS como: dsq-comments, dsq-comments-head, dsq-comments-body, dsq-comments-message, dsq-comments-eu-gosto-de-rolling-stones, dsq-comments-tudo-o-que-der-na-telha, etc. Como seria legal se esses nomes super extensos não fossem mais necessários, hein?

Problemas

Em meus testes, encontrei alguns empecilhos. Tentei utilizar scoped primeiramente em elementos que já tinham sido estilizados – não deu certo –, depois tentei aninhar estilos scoped e também não funcionou – francamente, não sei se é certo/possível fazer isto, e mesmo assim, penso que isso não serviria pra nada, é o tipo de coisa que só iria complicar a nossa vida (e de complexidade, já basta ser desenvolvedor web nos dias atuais), mas, pelo bem da ciência, realizei esse teste (aparentemente) inútil.

Aplicando scoped a elementos já estilizados

Quando a página já possuía estilos – por exemplo, no <head> – as propriedades que já tinham sido definidas não eram modificadas pelos estilos scoped, apenas aquelas que ainda não tinham sido alteradas por nenhum CSS. Por exemplo:

<head>
    <style>
        p { color: gray }
    </style>
</head>
<body>
    <p>I was crowned with a spike right thru my head.</p>
    <p>But it's all right now, in fact, it's a gas!</p>
    <div>
        <style scoped>
            p {
                color: red;
                font-size: 1.4em;
            }
        </style>
        <p>But it's all right, Im jumpin jack flash,</p>
        <p>Its a gas! gas! gas!</p>
    </div>
</body>

Se tentarmos fazer como acima, o resultado será:

I was crowned with a spike right thru my head.
But it’s all right now, in fact, it’s a gas!

But it’s all right, Im jumpin jack flash,
Its a gas! gas! gas!

Perceba que o único estilo de escopo que foi aplicado foi a regra font-size: 1.4em e a cor vermelha simplesmente foi ignorada. Sinceramente eu não faço a mínima ideia do porquê disto, também não vejo muito sentido – poderia até ser um erro de implementação do navegador, mas não posso afirmar isto com tanta veemência.

A pseudo-classe :scope

Depois de muito pesquisar, achei uma “solução”, por assim dizer. Eis que existe uma pseudo-classe :scope! Se usarmos esse cara como seletor das regras, tudo funciona perfeitamente. No exemplo acima, só faríamos:

<style scoped>
    /* adicionando a pseudo-classe :scope */
    :scope p {
        color: red;
        font-size: 1.4em;
    }
</style>

Agora sim, tudo como esperado:

I was crowned with a spike right thru my head.
But it’s all right now, in fact, it’s a gas!

But it’s all right, Im jumpin jack flash,
Its a gas! gas! gas!

Aninhando estilos scoped

Tentei também aninhar estilos scoped, mas parece que isso não funciona legal, e acredito que seja proposital. Mas essa parte eu deixo com vocês ;) Testem colocar um <style scoped> dentro de outro. Aqui mesmo eu não consegui muito resultado, ocorre o mesmo problema com as propriedades CSS que já foram definidas – são ignoradas e não funcionam nem mesmo adicionando a pseudo-classe :scoped. Se alguém obtiver algum resultado diferente do meu, comenta ai!

Suporte

No momento, apenas Google Chrome versão 20+.

Por Almir Filho

Desenvolvedor web na Globo.com. Mestrando em Ciência da Computação pela Universidade Federal do Maranhão. Co-fundador e autor do Loop Infinito, focado em produtividade, rocker e paraquedista nas horas vagas. Blog: almirfilho.com. Twitter: @almirfilho

http://loopinfinito.com.br

Mais posts do autor

Comentários (21)

  • Milton Filho

    Não curto essa mistura de css com html. Se rolasse algo assim com uma referencia pra um *.css seria bacana.

  • http://www.facebook.com/AdrianoCandidoCamilo Adriano Candido

    achei interessante, mas esse problema de compatibilidade com outros navegadores que torna esse recurso meio inútil por enquanto.

  • http://www.facebook.com/diegoleismann Diego Leismann Quadros

    Muito bom! adorei o post!

  • http://almirfilho.com/ Almir Filho

    De fato, nem eu curto ficar misturando as coisas. Mas o interessante é o quanto isso vai facilitar na componentização de aplicações (tópico O Pulo do Gato). Como toda tecnologia, esse é um recurso que deve ser utilizado apenas quando for realmente necessário.

  • http://twitter.com/sillero Gustavo Sillero

    Desde que foi proposto este atributo, só consegui pensar em uma utilidade: conter as cagadas dos desenvolvedores backend.

  • Marta

    Nossa, vai ser perfeito para projetos em sharepoint quando funcionar em mais browsers!

  • http://caiogondim.com/ Caio Gondim

    Muito bom o post.
    Qualidade.

  • Herick Correa

    Sei lá, ainda acho q um “!important” resolve…

  • http://www.eduardodesign.com/ Eduardo Matos

    Quando estava desenvolvendo com o pessoal aqui uma enquete e quiz, que seriam componentes (widgets) externos em páginas de terceiros achei a especificação do scoped bacana. Como ainda não é nativo e usar iframe nem sempre dá certo (cross-domain, https, etc…), o jeito foi apelar pro !important em tudo :(
    **existe alguns plugins de polyfill pra ele (https://github.com/thingsinjars/jQuery-Scoped-CSS-plugin), mas colocar style inline é uma abordagem que não me agrada (nem o !important…)

  • Eduardo Matos

    Fiz um teste rápido e verifiquei que isso afeta tudo que vem depois do style, o que certamente se tornaria um problema, pois um widget de um terceiro poderia afetar todo o seu CSS caso este fosse inserido no meio da página. Da maneira que funciona atualmente não consigo enxergar como uma solução pra modularização de componentes.

  • Felquis

    Hummmmm Parabéns Almir.

  • http://www.facebook.com/marco.nc.arruda Marco Antonio Arruda

    Muito bom o post, mas me parece que esse scope serve mais para reparos técnicos de urgência ou “gambiarra”

  • http://www.facebook.com/youry.stancatte Youry Sylvestrin Stancatte

    Não sou fã de “hardcode” não vi nenhuma vantagem em útlizar scope :/

  • http://www.eduardodesign.com/ Eduardo Matos

    A idéia era do scoped ser mais “forte” que o important, portanto você poderia inserir um componente externo numa página qualquer (via script, etc) e o css não ser influenciado por nada em volta.
    Mas pelo teste do Almir, provavelmente a idéia ainda não rolou pra elementos já estilizados :(

  • http://www.facebook.com/andrerambor André Rambor

    Voltar a misturar CSS com HTML??? Sei não…

  • http://twitter.com/diogocorrea Diogo Corrêa

    O Style scoped pode ajudar futuramente diminuir o uso desenfreado de iframes, que em questões de performance é uma pain in the ass.

  • http://www.facebook.com/rafael.g.amorim Rafael Gomes Amorim

    Taí um recurso novo, interessante, realmente facilitará em alguns casos, como o Almir sitou abaixo em uma réplica de um comentário.

    Mas fica a dica, é importante a leitura do artigo, todo conhecimento é válido, um dia Scope salvará muitos programadores hehehe.

  • Guto Foletto

    Mesmo levando modularização em conta, ficaria bizarro voltar a misturar html com css. Como você falou, pode ser que tenha utilidade, vejo eu que seja quando precisar poucas linhas de css, ou em um módulo mais simples… mas de outra forma uma folha de estilos externa ainda parece a melhor opção para modularização.

  • estenio

    sinceramente eu não usaria isto

  • Kaio Luis Fabiano

    Eu também acho

  • Kaio Luis Fabiano

    Conhecimento é tudo