This hydration warning appears when inline style attributes differ between server-rendered HTML and the initial client render. It commonly occurs in SSR frameworks like Next.js when components use browser APIs, dynamic styling, or CSS-in-JS libraries that generate different output on server versus client.
This warning is a React hydration error that occurs specifically when the style prop on an element differs between what was pre-rendered on the server (SSR/SSG) and what React generates during the first client-side render (hydration). During hydration, React expects to reuse the existing server-rendered DOM and simply attach event handlers, but when it detects mismatched attributes, it issues this warning. The warning indicates that React found an inline style attribute with different CSS properties or values between the server HTML and client JavaScript. This mismatch prevents React from efficiently hydrating the component and may cause the UI to be "stale" - React won't update the attribute to match the client-side props, instead keeping the server-rendered version. While the warning itself won't break your application, it signals that your server and client are rendering different output, which can lead to unexpected visual bugs, accessibility issues, or SEO problems where the initial HTML doesn't match what users ultimately see.
The most reliable fix is to defer any browser-specific logic to client-side only using the useEffect hook, which never runs during server rendering:
import { useState, useEffect } from 'react';
export default function Component() {
const [mounted, setMounted] = useState(false);
const [styles, setStyles] = useState({});
useEffect(() => {
setMounted(true);
// Safe to use window/document here
setStyles({
width: window.innerWidth > 768 ? '100%' : '50%'
});
}, []);
if (!mounted) return null; // Or return a loading placeholder
return <div style={styles}>Content</div>;
}This ensures the server renders a consistent fallback, then the client updates after hydration.
In Next.js, you can disable server-side rendering for components that must run client-only:
import dynamic from 'next/dynamic';
const ClientOnlyComponent = dynamic(
() => import('../components/ClientOnlyComponent'),
{ ssr: false }
);
export default function Page() {
return (
<div>
<ClientOnlyComponent />
</div>
);
}This tells Next.js to skip rendering this component on the server entirely, preventing any hydration mismatches.
If using styled-components, ensure you have the correct setup in your Next.js _document.tsx file:
import Document, { DocumentContext, Html, Head, Main, NextScript } from 'next/document';
import { ServerStyleSheet } from 'styled-components';
export default class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
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();
}
}
}This collects and injects server-side styles so they match the client.
For specific elements where you know the mismatch is harmless and unavoidable, you can suppress the warning:
<div suppressHydrationWarning>
<time>{new Date().toLocaleString()}</time>
</div>Important: This only works one level deep and doesn't fix the underlying issue. Use sparingly and only when you've confirmed the mismatch is intentional and won't cause visual bugs.
Audit your component props and state to ensure they produce identical output on both server and client:
// BAD - Will cause mismatch
function BadComponent() {
const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;
return <div style={{ width: isMobile ? '100%' : '50%' }}>Content</div>;
}
// GOOD - Consistent on server and client
function GoodComponent({ isMobile }) {
return <div style={{ width: isMobile ? '100%' : '50%' }}>Content</div>;
}Pass environment-specific values as props from a layout or page component that handles detection properly.
Browser extensions can inject attributes into your DOM that don't exist in the server HTML. Test in incognito mode:
# Test your app in incognito/private mode
# If the warning disappears, a browser extension is the culpritCommon culprits include ColorZilla, Grammarly, and translation extensions. While you can't control user extensions, you can add suppressHydrationWarning to the affected element or document the known issue.
Check if the libraries you're using have known hydration issues:
# Update libraries that commonly cause style mismatches
npm update @mui/material react-virtualized react-color
# Check GitHub issues for your specific library + "hydration"
# Many libraries have SSR-specific configuration optionsFor Material-UI components like Fade, you may need to disable transitions on the server or configure the StylesProvider properly.
Style serialization differences between JSDOM (used by React SSR) and actual browsers are a known issue tracked in React issue #11807. React purposely matches the style property by string value rather than parsing and normalizing CSS, which is why even semantically identical styles ("margin:0" vs "margin: 0") can trigger warnings.
For production applications, consider implementing a two-pass rendering strategy where the server renders a safe fallback UI, and the client immediately does a second render after hydration with the full dynamic styles. This adds a small performance cost but eliminates all hydration warnings.
In Next.js 13+ with app directory, you can use the "use client" directive to explicitly mark components as client-only, providing a clearer boundary than dynamic imports. This is especially useful for components that heavily depend on browser APIs.
If you're using CSS-in-JS, consider migrating to zero-runtime solutions like vanilla-extract or Linaria that generate static CSS at build time, eliminating server-client style mismatches entirely. Alternatively, newer libraries like Panda CSS and StyleX are designed with SSR hydration in mind from the ground up.
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite