CSS-in-JS
Advertencia: Las bibliotecas CSS-in-JS que requieren JavaScript en tiempo de ejecución no son compatibles actualmente con los Componentes del Servidor. El uso de CSS-in-JS con características más nuevas de React como Componentes del Servidor y Streaming requiere que los autores de bibliotecas admitan la última versión de React, incluyendo renderizado concurrente.
Estamos trabajando con el equipo de React en APIs de upstream para manejar activos CSS y JavaScript con soporte para Componentes del Servidor de React y arquitectura de streaming.
Las siguientes bibliotecas son compatibles en Componentes del Cliente en el directorio app
(orden alfabético):
chakra-ui
kuma-ui
@mui/material
@mui/joy
pandacss
styled-jsx
styled-components
stylex
tamagui
tss-react
vanilla-extract
Las siguientes están trabajando actualmente en la compatibilidad:
Es bueno saberlo: Estamos probando diferentes bibliotecas CSS-in-JS y agregaremos más ejemplos para bibliotecas que admitan características de React 18 y/o el directorio
app
.
Si deseas estilizar Componentes del Servidor, recomendamos usar Módulos CSS u otras soluciones que generen archivos CSS, como PostCSS o Tailwind CSS.
Configuración de CSS-in-JS en app
Configurar CSS-in-JS es un proceso de tres pasos que implica:
- Un registro de estilos para recolectar todas las reglas CSS en un renderizado.
- El nuevo hook
useServerInsertedHTML
para inyectar reglas antes de cualquier contenido que pueda usarlas. - Un Componente del Cliente que envuelve tu aplicación con el registro de estilos durante el renderizado inicial del lado del servidor.
styled-jsx
Usar styled-jsx
en Componentes del Cliente requiere usar v5.1.0
. Primero, crea un nuevo registro:
'use client'
import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { StyleRegistry, createStyleRegistry } from 'styled-jsx'
export default function StyledJsxRegistry({
children,
}: {
children: React.ReactNode
}) {
// Solo crea la hoja de estilos una vez con estado inicial diferido
// x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
const [jsxStyleRegistry] = useState(() => createStyleRegistry())
useServerInsertedHTML(() => {
const styles = jsxStyleRegistry.styles()
jsxStyleRegistry.flush()
return <>{styles}</>
})
return <StyleRegistry registry={jsxStyleRegistry}>{children}</StyleRegistry>
}
'use client'
import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { StyleRegistry, createStyleRegistry } from 'styled-jsx'
export default function StyledJsxRegistry({ children }) {
// Solo crea la hoja de estilos una vez con estado inicial diferido
// x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
const [jsxStyleRegistry] = useState(() => createStyleRegistry())
useServerInsertedHTML(() => {
const styles = jsxStyleRegistry.styles()
jsxStyleRegistry.flush()
return <>{styles}</>
})
return <StyleRegistry registry={jsxStyleRegistry}>{children}</StyleRegistry>
}
Luego, envuelve tu layout raíz con el registro:
import StyledJsxRegistry from './registry'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html>
<body>
<StyledJsxRegistry>{children}</StyledJsxRegistry>
</body>
</html>
)
}
import StyledJsxRegistry from './registry'
export default function RootLayout({ children }) {
return (
<html>
<body>
<StyledJsxRegistry>{children}</StyledJsxRegistry>
</body>
</html>
)
}
Styled Components
A continuación se muestra un ejemplo de cómo configurar styled-components@6
o más reciente:
Primero, habilita styled-components en next.config.js
.
module.exports = {
compiler: {
styledComponents: true,
},
}
Luego, usa la API de styled-components
para crear un componente de registro global que recolecte todas las reglas de estilo CSS generadas durante un renderizado, y una función para devolver esas reglas. Luego usa el hook useServerInsertedHTML
para inyectar los estilos recolectados en el registro dentro de la etiqueta HTML <head>
en el layout raíz.
'use client'
import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { ServerStyleSheet, StyleSheetManager } from 'styled-components'
export default function StyledComponentsRegistry({
children,
}: {
children: React.ReactNode
}) {
// Solo crea la hoja de estilos una vez con estado inicial diferido
// x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet())
useServerInsertedHTML(() => {
const styles = styledComponentsStyleSheet.getStyleElement()
styledComponentsStyleSheet.instance.clearTag()
return <>{styles}</>
})
if (typeof window !== 'undefined') return <>{children}</>
return (
<StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
{children}
</StyleSheetManager>
)
}
'use client'
import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { ServerStyleSheet, StyleSheetManager } from 'styled-components'
export default function StyledComponentsRegistry({ children }) {
// Solo crea la hoja de estilos una vez con estado inicial diferido
// x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet())
useServerInsertedHTML(() => {
const styles = styledComponentsStyleSheet.getStyleElement()
styledComponentsStyleSheet.instance.clearTag()
return <>{styles}</>
})
if (typeof window !== 'undefined') return <>{children}</>
return (
<StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
{children}
</StyleSheetManager>
)
}
Envuelve los children
del layout raíz con el componente de registro de estilos:
import StyledComponentsRegistry from './lib/registry'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html>
<body>
<StyledComponentsRegistry>{children}</StyledComponentsRegistry>
</body>
</html>
)
}
import StyledComponentsRegistry from './lib/registry'
export default function RootLayout({ children }) {
return (
<html>
<body>
<StyledComponentsRegistry>{children}</StyledComponentsRegistry>
</body>
</html>
)
}
Es bueno saberlo:
- Durante el renderizado del servidor, los estilos se extraerán a un registro global y se enviarán al
<head>
de tu HTML. Esto asegura que las reglas de estilo se coloquen antes de cualquier contenido que pueda usarlas. En el futuro, podríamos usar una próxima característica de React para determinar dónde inyectar los estilos.- Durante el streaming, los estilos de cada fragmento se recolectarán y agregarán a los estilos existentes. Después de que la hidratación del lado del cliente se complete,
styled-components
tomará el control como de costumbre e inyectará cualquier estilo dinámico adicional.- Usamos específicamente un Componente del Cliente en el nivel superior del árbol para el registro de estilos porque es más eficiente extraer reglas CSS de esta manera. Evita regenerar estilos en renderizados posteriores del servidor y evita que se envíen en la carga útil del Componente del Servidor.
- Para casos de uso avanzados donde necesites configurar propiedades individuales de la compilación de styled-components, puedes leer nuestra referencia de API de styled-components para Next.js para aprender más.