String-based CSS inlining functionality that directly injects critical CSS as <style> tags into HTML strings, providing immediate server-side rendering optimization.
Inlines critical CSS directly into HTML strings by parsing Emotion class names and injecting corresponding styles as <style> tags at appropriate positions.
/**
* Inlines critical CSS directly into HTML string
* @param html - Server-rendered HTML string containing Emotion class names
* @returns HTML string with critical CSS inlined as <style> tags
*/
function renderStylesToString(html: string): string;Usage Examples:
import React from "react";
import { renderToString } from "react-dom/server";
import { renderStylesToString } from "@emotion/server";
import styled from "@emotion/styled";
const Button = styled.button`
background: blue;
color: white;
padding: 10px 20px;
`;
const Header = styled.h1`
font-size: 24px;
margin: 0;
`;
const App = () => (
<div>
<Header>Welcome</Header>
<Button>Click me</Button>
</div>
);
// Inline critical CSS
const htmlWithStyles = renderStylesToString(renderToString(<App />));
console.log(htmlWithStyles);
// Output includes:
// <style data-emotion="css abc123 def456">
// /* CSS for Button and Header components */
// </style>
// <div>
// <h1 class="css-def456">Welcome</h1>
// <button class="css-abc123">Click me</button>
// </div>The function generates <style> tags with specific attributes:
Example with Nonce:
import createEmotionServer from "@emotion/server/create-instance";
import createCache from "@emotion/cache";
// Create cache with nonce for Content Security Policy
const cache = createCache({
key: "css",
nonce: "random-nonce-value"
});
const { renderStylesToString } = createEmotionServer(cache);
const htmlWithStyles = renderStylesToString(renderToString(<App />));
// Generated style tag includes: nonce="random-nonce-value"The inlining process follows a sophisticated strategy:
Advanced Usage with Multiple Components:
import React from "react";
import { renderToString } from "react-dom/server";
import { renderStylesToString } from "@emotion/server";
import styled from "@emotion/styled";
const GlobalStyle = styled.div`
font-family: Arial, sans-serif;
* {
box-sizing: border-box;
}
`;
const Card = styled.div`
background: white;
border: 1px solid #ccc;
border-radius: 8px;
padding: 16px;
`;
const Title = styled.h2`
color: #333;
margin: 0 0 16px 0;
`;
const App = () => (
<GlobalStyle>
<Card>
<Title>Card Title</Title>
<p>Card content goes here.</p>
</Card>
</GlobalStyle>
);
const htmlWithStyles = renderStylesToString(renderToString(<App />));
// Results in optimally ordered and deduplicated CSS injectionExpress.js Server:
import express from "express";
import React from "react";
import { renderToString } from "react-dom/server";
import { renderStylesToString } from "@emotion/server";
const app = express();
app.get("/", (req, res) => {
const htmlWithStyles = renderStylesToString(renderToString(<App />));
const fullPage = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My App</title>
</head>
<body>
<div id="root">${htmlWithStyles}</div>
</body>
</html>
`;
res.send(fullPage);
});Next.js Custom Document:
import Document, { Html, Head, Main, NextScript } from "next/document";
import { renderStylesToString } from "@emotion/server";
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const originalRenderPage = ctx.renderPage;
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => renderStylesToString(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return initialProps;
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}