Quem desenvolve aplicações utilizando Angular normalmente está acostumado com o uso do CSS Modules. Essa feature é responsável por manter, em somente um componente, o escopo de um arquivo de estilo (.css, sass etc.). Isso traz algumas vantagens, como evitar colisões com classes e seletores usados em outros lugares da aplicação, além de facilitar a localização dos estilos que efetivamente estão sendo aplicados àquele componente.

Como aqui no blog da Iteris estamos sempre trazendo dicas e novidades, confira um passo a passo que produzimos para demonstrar a criação de uma nova aplicação com esse comportamento, tanto em Angular como em React.


The Angular Way

Primeiramente, abra um shell e instale o Angular com o seguinte comando:

npm install -g @angular/cli

Após a instalação, execute os comandos a seguir para criar uma nova aplicação e executá-la:

ng new angular-app
cd angular-app
ng-serve
Aplicação em Angular inicial.
Aplicação Angular inicial

Criaremos algo bem simples para demonstrar o funcionamento do CSS Modules. Nossa aplicação de exemplo terá um componente com uma div colorida e um “componente filho” com uma div exatamente igual, mas com uma cor diferente.

Comece criando o componente filho executando o comando no shell:

ng generate component child

Após a criação do componente, altere o conteúdo do arquivo src/style.css conforme o trecho abaixo:

html, body {
    height: 100%;
}

.container {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
}

.box {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 80%;
    height: 80%;
}

.red {
    background-color: red;
}

Agora, altere o conteúdo do arquivo src/app/app.component.html:

<div class="container">

    <div class="box red">
        <app-child></app-child>
    </div>

</div>

Por fim, altere o conteúdo do arquivo src/app/child/child.component.html:

<div class="box red"></div>
Aplicação em Angular após as alterações.
Aplicação após as alterações

Para conseguir visualizar o CSS Modules em funcionamento, adicione o conteúdo a seguir no arquivo src/app/child/child.component.css:

:host {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.red {
    background-color: blue;
}
Aplicação em Angular após novo CSS.
Aplicação após novo CSS
Source - Aplicação em Angular após novo CSS
Source – Aplicação após novo CSS

Analisando o source do HTML gerado pela aplicação, podemos ver que na div do componente filho foi adicionado dinamicamente o atributo “_ng-content-wpi-c1”. Esse mesmo atributo é utilizado no seletor do CSS do componente filho, sendo esse mais específico que a classe do arquivo styles.css.

Como só a div do componente filho teve o atributo adicionado, somente ela teve a cor alterada. Essa é a maneira do Angular forçar o escopo de estilos em seus componentes.

Mas… e se quisermos obter esse mesmo funcionamento em React?

The React Way

Para a criação de projetos, o React possui diferentes toolchains que variam de acordo com a necessidade (renderizados no servidor, conteúdo estático etc.). Nosso exemplo utilizará o Create React App, que é a toolchain recomendada para a criação de single-page apps.

Para criar e executar um projeto utilizando o Create React App, execute os seguintes comandos no shell:

npx create-react-app react-app
cd react-app
npm start
Aplicação inicial em React
Aplicação React inicial

Após a criação do projeto, crie uma pasta chamada Child dentro de src e crie os arquivos Child.js e Child.css. Agora, iremos replicar o mesmo layout que foi utilizado no projeto Angular.

Altere o conteúdo do arquivo src/App.js:

import React from 'react';
import './App.css';
import Child from './Child/Child';

function App() {
    return (
        <div className="container">
            <div className="box red">
                <Child></Child>
            </div>
        </div>
    );
}

export default App;

Agora, altere o conteúdo do arquivo src/App.css:

/* You can add global styles to this file, and also import other style files */
html, body, #root {
    height: 100%;
}

.container {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
}

.box {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 80%;
    height: 80%;
}

.red {
    background-color: red;
}

Altere o conteúdo do arquivo src/Child/Child.js:

import React from 'react';
import './Child.css'

function Child() {
    return (
        <div className="red"></div>
    );
}

export default Child;

Por fim, altere o conteúdo do arquivo src/Child/Child.css:

.red {
    background-color: blue;
}
Aplicação em React após alterações.
Aplicação após alterações
Source - Aplicação em React após alterações
Source – Aplicação após alterações

Podemos observar que o React simplesmente adicionou o CSS de nosso componente Child aos styles sem nenhuma alteração, fazendo com que as duas divs, pai e filho, tenham suas cores alteradas.

Então como implementamos o CSS Modules nesse caso?

Essa feature não é algo embutido no próprio React, e sim uma configuração habilitada no Webpack pelo Create React App. Para o Webpack identificar que um arquivo de estilo deve ser utilizado em um escopo de componente, o arquivo de css de nosso componente Child deve seguir o formato [nome].module.css. Em nosso caso, devemos alterar o nome do nosso arquivo de Child.css para Child.module.css. Não se esqueça de alterar a referência no Child.js.

Aplicação em React após renomear css
Aplicação após renomear css
Source – Aplicação após renomear css

Por que será que não funcionou? Na verdade, o funcionamento do CSS Modules em React é um pouco diferente da versão em Angular.

Como pudemos ver em nossa aplicação em Angular, ao gerar o HTML e o CSS que será provido do navegador, o compilador do Angular adicionou atributos aos elementos do nosso componente filho, além de adicionar o mesmo atributo aos seletores do arquivo de estilo do componente.

Para a aplicação React, o Webpack cria para os arquivos seletores únicos, que seguem a nomenclatura de [nome].module.css. Então precisamos, de alguma maneira, informar esse seletor gerado em nosso componente. Felizmente, isso é muito simples de ser feito. Altere o arquivo src/Child/Child.js conforme o código abaixo:

import React from 'react';
import styles from './Child.module.css'

function Child() {
    return (
        <div className={`box ${styles.red}`}></div>
    );
}

export default Child;
CSS Modules com React em funcionamento
CSS Modules com React em funcionamento
Source - CSS Modules com React em funcionamento
Source – CSS Modules com React em funcionamento

Agora sim! O seletor gerado pelo Webpack foi utilizado corretamente em nosso componente filho, fazendo com que ficasse com a cor diferente.

Existem outras funcionalidades bem úteis disponibilizadas pelo Create React App, portanto busque sempre consultar sua documentação, além da documentação oficial do React, para acompanhar as novidades.

O projeto pode ser baixado pelo link: https://github.com/sandrocaseiro/react-css-module.


A Iteris tem especialistas aptos a avaliar sua ideia de negócio digital de ponta a ponta e recomendar o melhor caminho para chegar no software que você imagina para sua empresa. Entre em contato e saiba mais sobre como podemos te ajudar nos desafios da sua TI.