React
Styling en React y relación con CSS
Explica cómo React comunica estructura y estados visuales mientras CSS resuelve presentación, layout, responsive, temas, variantes y accesibilidad.
- Última actualización
- Actualizada
- Nivel
- Aplicación
React
Explica cómo React comunica estructura y estados visuales mientras CSS resuelve presentación, layout, responsive, temas, variantes y accesibilidad.
React decide qué estructura y estados visuales debe expresar un componente. CSS continúa siendo responsable de layout, presentación, adaptación y gran parte de la experiencia visual.
React no incluye un sistema de estilos obligatorio. Un componente puede comunicar su estado mediante clases, atributos, custom properties o estilos inline:
type AlertProps = {
tone: "info" | "success" | "warning" | "danger";
children: React.ReactNode;
};
function Alert({ tone, children }: AlertProps) {
return (
<div className={`alert alert--${tone}`} role="status">
{children}
</div>
);
}.alert {
padding: 1rem;
border-radius: 0.75rem;
}
.alert--danger {
background: var(--danger-surface);
color: var(--danger-text);
}React expresa la variante. CSS resuelve su apariencia.
En JSX se utiliza className:
<button className="button button--primary">Guardar</button>Las clases pueden construirse de forma explícita:
const className = [
"button",
`button--${variant}`,
isLoading && "button--loading",
]
.filter(Boolean)
.join(" ");Una utilidad de combinación puede mejorar legibilidad, pero no cambia el modelo conceptual.
<div style={{ width: progress + "%" }} />Son útiles para valores realmente dinámicos y pequeños. Limitaciones:
:hover.No son automáticamente lentos ni incorrectos; dependen del caso.
React puede pasar valores dinámicos hacia CSS:
<div
className="progress"
style={{ "--progress": `${progress}%` } as React.CSSProperties}
/>.progress::before {
width: var(--progress);
}Esto mantiene la lógica dinámica en React y la presentación en CSS.
Los estilos globales son apropiados para:
El riesgo aparece cuando selectores amplios crean dependencias difíciles de rastrear.
import styles from "./ProductCard.module.css";
function ProductCard() {
return <article className={styles.card}>...</article>;
}Los nombres quedan aislados por build. Aportan co-location sin introducir runtime de estilos.
<button className="inline-flex items-center rounded-md px-4 py-2">
Guardar
</button>Puede acelerar composición y mantener consistencia cuando existe un sistema de tokens. El coste es que el contrato visual vive en strings de utilities y puede requerir abstraer variantes repetidas.
No conviertas Tailwind u otra herramienta en requisito conceptual de React.
Existen estrategias runtime y build-time. Evalúa:
No asumas que toda solución CSS-in-JS tiene el mismo comportamiento.
Una API de variantes debe representar estados válidos:
type ButtonProps =
| { kind: "link"; href: string; onClick?: never }
| { kind: "action"; onClick: () => void; href?: never };La apariencia no debe ocultar la semántica: un botón que parece enlace continúa siendo botón si ejecuta una acción.
Context puede distribuir la elección del tema, pero CSS suele aplicar los tokens:
<html data-theme={theme}>:root {
--surface: white;
--text: #111;
}
[data-theme="dark"] {
--surface: #111;
--text: white;
}No guardes cada color en state. Guarda la preferencia o configuración mínima.
Tokens expresan decisiones reutilizables:
:root {
--space-2: 0.5rem;
--radius-md: 0.75rem;
--color-primary: #5b5bd6;
}React consume tokens mediante clases y estructura. El notebook de CSS profundiza en cascada, layout, responsive y arquitectura de estilos.
Un componente real debe considerar:
No modeles todos como booleans independientes si pueden formar combinaciones inválidas.
Una librería visual ofrece componentes con estilos. Una librería headless ofrece comportamiento y accesibilidad sin imponer apariencia.
Evalúa:
No asumas que una librería accesible continúa siéndolo después de personalizaciones que rompen su contrato.
Mantener estilos cerca del componente puede ayudar a localizar cambios. No implica insertar todos los valores visuales dentro del archivo TSX.
La frontera útil depende de:
React no necesita state para cada breakpoint:
const [isMobile, setIsMobile] = useState(false);Para layout visual, media queries suelen ser la solución correcta:
.grid {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 48rem) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}Usa JavaScript cuando el comportamiento, no solo la presentación, cambia según una capability del entorno.
Los estilos deben preservar:
React comunica estados; CSS debe hacerlos perceptibles.
Problemas potenciales:
Mide en navegador. El número de clases no determina por sí solo el rendimiento.
className, styles y custom properties son mecanismos, no arquitecturas completas.Producción y entrega de aplicaciones React conecta build, bundles, monitoring y compatibilidad con la experiencia real.