Componentes React são estilizados com CSS comum. Dê uma classe aos elementos com a prop className e escreva as regras em uma folha de estilos, use a prop style para valores que vêm do JavaScript e recorra a CSS Modules ou ao Tailwind quando o projeto crescer. O exemplo abaixo define o CSS em um elemento <style> para poder rodar nesta página; em um projeto ele ficaria em um arquivo .css.
Troque #2563eb por #16a34a na regra .btn e o botão fica verde. Tudo o que você sabe de CSS vale aqui: seletores, media queries, estados de hover, animações.
className, não class
O JSX compila para JavaScript, onde class é uma palavra reservada, então o React usa className, o nome que o próprio DOM usa para essa propriedade (element.className). O navegador continua recebendo um atributo class comum. A mesma troca de nome vale para htmlFor em vez de for nos labels. O React 19 aceita class com um aviso em desenvolvimento, mas className é o nome correto e o que todo código usa.
className recebe uma string, então várias classes são separadas por espaço: className="btn btn-primary". Como o valor é JavaScript, ele pode ser calculado.
Classes condicionais
Para adicionar uma classe só em alguns casos, monte a string com um ternário ou uma template literal. Uma barra de abas que destaca a aba selecionada é o caso clássico.
Clique em Lessons e o sublinhado se move, porque agora só a string desse botão contém active. Reviews recebe a classe disabled e o atributo disabled, então fica cinza e ignora cliques. A template literal deixa espaços extras quando uma condição é falsa, e os navegadores os ignoram. Quando um componente tem muitas classes condicionais, um array fica mais organizado:
const classes = ['tab', isActive && 'active', isDisabled && 'disabled']
.filter(Boolean)
.join(' ');
Muitos projetos usam o pequeno pacote clsx para a mesma tarefa: clsx('tab', { active: isActive, disabled: isDisabled }).
A prop style
A prop style recebe um objeto JavaScript, não uma string. É por isso que ela tem chaves duplas: o par de fora abre uma expressão JavaScript, o par de dentro é o literal de objeto. Os nomes das propriedades são camelCase (backgroundColor, fontSize, borderRadius), e os valores são strings ou números. Um número em uma propriedade de comprimento vira pixels, então padding: 12 significa 12px.
Estilos inline brilham quando um valor é calculado no momento da renderização, como a largura de uma barra de progresso.
Clique em Add 10% até a barra encher e ela fica verde. Repare em width: percent + '%': um número sozinho significaria pixels, então unidades diferentes de px vão em uma string. Propriedades sem unidade continuam números simples, como opacity: 0.8, zIndex: 2, flexGrow: 1 e lineHeight: 1.5 (que é um multiplicador, não pixels).
Estilos inline têm limites. Eles não conseguem expressar :hover, :focus, media queries nem animações com keyframes, e cada elemento carrega a própria cópia das regras. Use-os para os valores dinâmicos e deixe o resto no CSS.
Variáveis CSS a partir de props
Um bom meio-termo é definir uma propriedade personalizada do CSS em style e usá-la na sua folha de estilos. As regras ficam no CSS, estados de hover incluídos, e só o valor vem do JavaScript.
Escolha uma nova cor e os dois botões a acompanham, e o preenchimento no hover continua funcionando porque é CSS puro. Os nomes de propriedades personalizadas mantêm os hifens no objeto style, então vão entre aspas: { '--accent': accent }.
Arquivos CSS
Em um projeto real você escreve estilos em arquivos .css e os importa no componente que precisa deles. Com o Vite, o import basta: a ferramenta de build vê import './Button.css', adiciona a folha de estilos à página durante o desenvolvimento e a empacota em um arquivo CSS para produção. Não há export para usar; o import existe só pelo efeito colateral.
// Button.jsx
import './Button.css';
export default function Button({ children }) {
return <button className="button">{children}</button>;
}
/* Button.css */
.button {
background: #2563eb;
color: white;
border-radius: 6px;
}
O problema é que toda folha de estilos importada é global. Uma regra .button em Button.css estiliza todos os elementos com essa classe, em qualquer parte do app, e dois arquivos que definem .title sobrescrevem um ao outro. As equipes lidam com isso com convenções de nomes como BEM (.card__title) ou com CSS Modules.
CSS Modules
Um arquivo terminado em .module.css é um CSS Module. Importá-lo dá a você um objeto que mapeia cada nome de classe que você escreveu para um nome único gerado, então uma classe só pode se aplicar onde você a usa. O Vite e o Next.js suportam isso sem configuração.
// Card.jsx
import styles from './Card.module.css';
export default function Card({ title, children, featured }) {
return (
<section className={featured ? `${styles.card} ${styles.featured}` : styles.card}>
<h3 className={styles.title}>{title}</h3>
{children}
</section>
);
}
/* Card.module.css */
.card { border: 1px solid #ddd; border-radius: 10px; padding: 16px; }
.featured { border-color: #2563eb; }
.title { margin: 0; }
No navegador a classe aparece como algo parecido com _card_1x2ab_1. Outro componente pode definir o próprio .title e os dois nunca colidem. Você escreve CSS normal, regras de hover e media queries incluídas, e é por isso que CSS Modules são um padrão comum para estilos de componentes.
Tailwind CSS com React
O Tailwind segue outro caminho: em vez de escrever regras, você compõe pequenas classes utilitárias direto no className. px-4 define o padding horizontal, rounded-lg arredonda os cantos, hover:bg-blue-700 muda o fundo no hover. O Tailwind varre seus arquivos e gera CSS só para as classes que você usa.
Configurá-lo em um app React com Vite (Tailwind v4) leva três passos:
npm install tailwindcss @tailwindcss/vite
// vite.config.js
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
export default defineConfig({
plugins: [react(), tailwindcss()],
});
/* src/index.css, imported from main.jsx */
@import "tailwindcss";
Depois estilize os componentes com classes:
function UpgradeCard({ active }) {
return (
<div className="max-w-xs rounded-xl border border-gray-200 p-4">
<h3 className="mb-2 text-lg font-semibold">Pro plan</h3>
<button
className={`rounded-md px-4 py-2 text-white ${active ? 'bg-green-600' : 'bg-blue-600 hover:bg-blue-700'}`}
>
{active ? 'Active' : 'Upgrade'}
</button>
</div>
);
}
O Tailwind não está disponível nos editores desta página, então aparece como código estático. Classes condicionais funcionam exatamente como no exemplo das abas acima, mas escreva cada nome de classe por inteiro: o Tailwind encontra as classes varrendo o texto do seu código, então um nome montado em tempo de execução como `bg-${color}-600` nunca é gerado.
Quando usar qual
- Arquivos CSS comuns servem para apps pequenos e estilos globais (resets, fontes, layout da página). Fique de olho em colisões de nomes de classe conforme o app cresce.
- CSS Modules servem para a maioria dos estilos de componentes: CSS normal, com escopo automático, sem biblioteca extra.
- Tailwind serve para equipes que preferem estilizar na marcação e querem uma escala de design compartilhada para espaçamento e cores.
- A prop
styleé para valores calculados no momento da renderização: uma largura, uma posição, a cor escolhida por um usuário. Combine-a com variáveis CSS para manter as regras de hover e de media no CSS.
Você pode misturá-los. Um app típico tem uma folha de estilos global, CSS Modules ou Tailwind para os componentes e alguns estilos inline para valores dinâmicos. Bibliotecas de CSS-in-JS como styled-components e Emotion são outra opção que você vai encontrar em códigos mais antigos. A página sobre como instalar o React mostra como iniciar um projeto Vite em que tudo isso funciona.
Perguntas frequentes
Por que o React usa className em vez de class?
O JSX compila para JavaScript, e class é uma palavra reservada ali. O React usa o nome da propriedade do DOM, className, que também é como element.className se chama em JavaScript puro. No HTML ela continua virando um atributo class normal.
Como escrevo estilos inline no React?
Passe um objeto para a prop style, com nomes de propriedades em camelCase: style={{ backgroundColor: 'teal', fontSize: 18 }}. As chaves de fora abrem uma expressão JavaScript e as de dentro são o objeto. Números viram pixels nas propriedades que recebem um comprimento.
Como adiciono uma classe condicionalmente no React?
Monte a string em JavaScript: className={isActive ? 'tab active' : 'tab'} ou uma template literal como className={`tab ${isActive ? 'active' : ''}`}. Para muitas condições, um pequeno auxiliar como o pacote clsx mantém tudo legível.
Os arquivos CSS no React são globais?
Sim. import './App.css' adiciona a folha de estilos à página inteira, então os nomes de classe dela podem colidir com os de outros arquivos. CSS Modules (App.module.css) renomeiam cada classe para um nome único, de modo que ela só se aplica onde você a importa.
Como uso Tailwind com React?
Em um projeto Vite, instale tailwindcss e @tailwindcss/vite, adicione o plugin ao vite.config.js e coloque @import "tailwindcss"; no topo do seu arquivo CSS principal. Depois escreva classes utilitárias no className, como className="px-4 py-2 rounded bg-blue-600 text-white".