How to fix Warning: Did not expect server HTML to contain a <style> tag in React

ReactINTERMEDIATEMEDIUMUpdated Dec 8, 2025· 124 views

This React hydration warning occurs when CSS-in-JS libraries inject style tags during server-side rendering that React does not expect during client-side hydration, causing a mismatch between server and client HTML.

Quick fix

Fixes Warning: Did not expect server HTML to contain a <style> tag

// pages/_document.js
import Document, { Html, Head, Main, NextScript } from 'next/document';
import { ServerStyleSheet } from 'styled-components';

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      };
    } finally {
      sheet.seal();
    }
  }

  render() {
    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}
  1. Verify your CSS-in-JS library SSR configuration
  2. Install and configure the styled-components Babel plugin
  3. Configure Emotion for SSR with proper cache setup
  4. Extract critical styles on the server for Emotion
react — error
// pages/_document.js
import Document, { Html, Head, Main, NextScript } from 'next/document';
import { ServerStyleSheet } from 'styled-components';
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const sheet = new ServerStyleSheet();
const originalRenderPage = ctx.renderPage;
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App {...props} />),
});
const initialProps = await Document.getInitialProps(ctx);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
</>
),
};
} finally {
sheet.seal();
}
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}
Warning: Did not expect server HTML to contain a <style> tag

What this error means

This warning is a hydration error that appears when React detects style tags in the server-rendered HTML that were not expected during client-side hydration. Hydration is the process where React attaches event handlers to server-rendered HTML, and it expects the server and client markup to be identical. The error typically occurs with CSS-in-JS solutions like styled-components, Emotion, or other libraries that inject styles dynamically. These libraries often render styles as a side effect of component rendering, meaning React needs to fully render the page to determine which components are used and what styles they need. When the server renders styles in one way but the client expects them differently, React detects this mismatch and issues a warning. While this warning does not break your application, it indicates that React had to do extra work to reconcile the differences between server and client markup, which can impact performance and may lead to visual flashes or incorrect initial renders.

Typical symptoms

  • Warning message in browser console: "Did not expect server HTML to contain a <style> in <div>"
  • Styles flashing or changing briefly on initial page load (FOUC - Flash of Unstyled Content)
  • Console warnings only appear in development mode with React strict checks enabled
  • Warning occurs specifically on pages using server-side rendering (SSR) or static generation
  • Multiple warnings appear if many styled components are used on the page
  • Styles work correctly after hydration completes, but the warning persists
  • Warning appears when using CSS-in-JS libraries like styled-components or Emotion with Next.js or Remix

Common causes

  1. CSS-in-JS library not properly configured for server-side rendering
  2. Missing or incorrect ServerStyleSheet setup in styled-components SSR configuration
  3. Emotion cache not properly configured with CacheProvider during SSR
  4. Style extraction not performed on the server before sending HTML to client
  5. Hydration function not called on client-side for Emotion extractCritical
  6. Babel plugin for styled-components not installed, causing non-deterministic class names
  7. Styles injected in document head on server but expected in different location on client
  8. Using CSS-in-JS with frameworks like Next.js or Remix without proper SSR setup

How to fix "Warning: Did not expect server HTML to contain a <style> tag"

1Verify your CSS-in-JS library SSR configuration

Check if you have properly configured server-side rendering for your CSS-in-JS library. For styled-components with Next.js, create a custom _document.js:

javascript
// pages/_document.js
import Document, { Html, Head, Main, NextScript } from 'next/document';
import { ServerStyleSheet } from 'styled-components';

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const sheet = new ServerStyleSheet();
    const originalRenderPage = ctx.renderPage;

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        });

      const initialProps = await Document.getInitialProps(ctx);
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      };
    } finally {
      sheet.seal();
    }
  }

  render() {
    return (
      <Html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

This ensures styled-components collects styles during server rendering and injects them properly.

2Install and configure the styled-components Babel plugin

The Babel plugin ensures deterministic class names and prevents checksum mismatches. Install it:

bash
npm install --save-dev babel-plugin-styled-components

Then add to your .babelrc or babel.config.js:

json
{
  "presets": ["next/babel"],
  "plugins": [["styled-components", { "ssr": true }]]
}

For Next.js 12+, you can use the built-in compiler option in next.config.js:

javascript
module.exports = {
  compiler: {
    styledComponents: true,
  },
};
3Configure Emotion for SSR with proper cache setup

If using Emotion, set up the cache provider and extract critical styles. Create an Emotion cache:

javascript
// lib/createEmotionCache.js
import createCache from '@emotion/cache';

export default function createEmotionCache() {
  return createCache({ key: 'css', prepend: true });
}

In your _app.js (Next.js) or root component:

javascript
import { CacheProvider } from '@emotion/react';
import createEmotionCache from '../lib/createEmotionCache';

const clientSideEmotionCache = createEmotionCache();

function MyApp({ Component, emotionCache = clientSideEmotionCache, pageProps }) {
  return (
    <CacheProvider value={emotionCache}>
      <Component {...pageProps} />
    </CacheProvider>
  );
}
4Extract critical styles on the server for Emotion

In your custom _document.js, extract and inject critical styles:

javascript
import Document, { Html, Head, Main, NextScript } from 'next/document';
import createEmotionServer from '@emotion/server/create-instance';
import createEmotionCache from '../lib/createEmotionCache';

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const originalRenderPage = ctx.renderPage;
    const cache = createEmotionCache();
    const { extractCriticalToChunks } = createEmotionServer(cache);

    ctx.renderPage = () =>
      originalRenderPage({
        enhanceApp: (App) => (props) => (
          <App emotionCache={cache} {...props} />
        ),
      });

    const initialProps = await Document.getInitialProps(ctx);
    const emotionStyles = extractCriticalToChunks(initialProps.html);
    const emotionStyleTags = emotionStyles.styles.map((style) => (
      <style
        data-emotion={`${style.key} ${style.ids.join(' ')}`}
        key={style.key}
        dangerouslySetInnerHTML={{ __html: style.css }}
      />
    ));

    return {
      ...initialProps,
      emotionStyleTags,
    };
  }

  render() {
    return (
      <Html>
        <Head>{this.props.emotionStyleTags}</Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}
5Consider alternative styling solutions

If hydration warnings persist and are difficult to resolve, consider migrating to styling solutions that work better with SSR:

Tailwind CSS:

bash
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

CSS Modules (built into Next.js):

javascript
import styles from './Component.module.css';

export default function Component() {
  return <div className={styles.container}>Content</div>;
}

Both solutions generate static CSS that does not cause hydration mismatches.

6Verify styles are injected in the correct location

Ensure your CSS-in-JS library injects styles in the <head> tag, not in the <body>. Check your configuration:

javascript
// For Emotion, use prepend: true in cache config
const cache = createCache({ key: 'css', prepend: true });

// For styled-components, styles should automatically go in <head>
// If they don't, check your ServerStyleSheet implementation

Inspect your rendered HTML to confirm style tags appear in <head> on both server and client.

7Clear Next.js cache and rebuild

After making configuration changes, clear the Next.js cache and rebuild:

bash
rm -rf .next
npm run build
npm run start

For development, restart your dev server:

bash
npm run dev

Configuration changes to Babel plugins or Next.js compiler options require a full restart.

Advanced notes

For frameworks using streaming SSR (like React 18's Suspense), CSS-in-JS solutions may require double-rendering: the first render extracts all necessary styles, and the second render streams to the browser with those styles included. This can impact server performance.

If using React Server Components in Next.js 13+ App Router, CSS-in-JS libraries that rely on runtime JavaScript may not work in server components. Stick to CSS Modules, Tailwind, or other zero-runtime solutions for server components, and only use CSS-in-JS in Client Components (marked with "use client").

The suppressHydrationWarning={true} attribute can silence this warning on specific elements, but it's an escape hatch that should be used sparingly. It doesn't fix the underlying issue and may hide real problems.

For production builds, these warnings are typically not shown to users as React's development checks are disabled. However, the underlying hydration mismatch still causes React to do extra work, potentially impacting initial render performance.

Frequently asked questions

What does "Warning: Did not expect server HTML to contain a <style> tag" mean?
This warning is a hydration error that appears when React detects style tags in the server-rendered HTML that were not expected during client-side hydration. Hydration is the process where React attaches event handlers to server-rendered HTML, and it expects the server and client markup to be identical. The error typically occurs with CSS-in-JS solutions like styled-components, Emotion, or other libraries that inject styles dynamically.
How do I fix "Warning: Did not expect server HTML to contain a <style> tag"?
This React hydration warning occurs when CSS-in-JS libraries inject style tags during server-side rendering that React does not expect during client-side hydration, causing a mismatch between server and client HTML.
What causes "Warning: Did not expect server HTML to contain a <style> tag"?
CSS-in-JS library not properly configured for server-side rendering Missing or incorrect ServerStyleSheet setup in styled-components SSR configuration Emotion cache not properly configured with CacheProvider during SSR
Is the "Warning: Did not expect server HTML to contain a <style> tag" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading