Motivação
Conforme o projeto vai crescendo, muitos problemas começam a surgir por decisões tomadas no início, quando aquilo não parecia ser um problema ou talvez nem fosse imaginado. Um desses problemas pode ser a falta de padrão nos estilos, e um problema que é originado a partir disso é a confusão gerada com os classNames.
Problema
O problema com os classNames ocorre da seguinte maneira. Imaginem um nome de className bastante utilizado por todos, no caso irei explicar utilizando o nome "title". Todos os lugares em que utilizamos o "title" precisamos criar um nome composto para que não haja globalidade entre os estilos, então caso formos utilizar dentro de um card, criaremos o "card-title", caso seja uma modal, será "modal-title", e cada vez ficará mais difícil para pensar num bom nome de className para cada componente.
Solucão
Desde a versão 2 do CRA (create-react-app) temos a opcão de criar estilos únicos para cada componente, utilizando os css-modules. Os css-modules são arquivos css em que os classNames e animações são definidos localmente, isso significa que os estilos ali criados, só serão declarados dentro daquele escopo, e não globalmente, evitando conflitos entre estilos.
Explicação
Abaixo temos um arquivo .jsx contendo um card simples sem a utilização de css-modules:
import React from 'react';
import './styles.scss';
function Card() {
return (
<div className="container">
<h1 className="title">Card title</h1>
<span className="description">Card description</span>
</div>
);
}
export default Card;
E esses são os estilos que devem ser aplicados para esse card:
.container {
display: flex;
flex-direction: column;
padding: 20px;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.3);
}
.title {
font-size: 18px;
font-weight: 700;
}
.description {
font-size: 14px;
}
Porém nosso card está aparecendo da seguinte forma:
Ao inspecionar, vemos que em outro lugar do projeto existe um mesmo className description que altera a cor e tamanho da fonte:
A saída agora seria renomear os classNames utilizados no card, porém com os css-modules temos uma maneira melhor de fazer isso. O primeiro passo é alterar o nome do seu arquivo de estilos para o seguinte formato: [name].module.scss
.
Depois de fazer isso, deverá alterar seu import dos estilos e a utilização dos classNames para a seguinte forma:
import React from 'react';
import styles from './styles.module.scss';
function Card() {
return (
<div className={styles.container}>
<h1 className={styles.title}>Card title</h1>
<span className={styles.description}>Card description</span>
</div>
);
}
export default Card;
E então nosso componente aparecerá da seguinte forma (correta):
Você deve estar se perguntando como que isso funciona por baixo dos panos. Bom, o css-modules cria um className único para cada local em que é utilizado, e isso é feito da seguinte forma: [filename]\_[classname]\_\_[hash]
.
Abaixo seguem dois exemplos, um de como é compilado o card sem o css-modules, e outro com:
Sem css-modules
Com css-modules
Conclusão
Vimos que a utilização do css-modules possui muitos pontos positivos e que a sua implementação é muito simples, não precisando de um grande planejamento ou tempo, podendo fazer sua utilização para novas features e com o tempo ir aplicando nas antigas.
Top comments (3)
Muito bom usar css com react mas sabe se isso é possivel com sass tambem ? em um os projetos da empresa a gente tem esse problema de conflito de classes, pra ter o aninhamento de classes como sass e ainda gerar de uma forma randomica no build seria a melhor opção usar css-in-js ?
Isso é bem bom, mas particularmente eu prefiro usar o styled-components que também da pra isolar cada componente com seus respectivos estilos.
Muito bom esse conteúdo!!