← Back to React Course | Chapter 11: Styling in React | Lesson 7 of 8

Responsive Design in React

Responsive design in React is like furniture that automatically rearranges itself depending on whether it's in a tiny apartment or a big house.

CSS Media Queries Still Come First

For most responsive styling — different paddings, font sizes, or layouts at different widths — plain CSS media queries remain the right tool, since they're handled natively by the browser without any JavaScript overhead or re-renders.

Note: Reach for a React-based responsive hook only when you need to render fundamentally DIFFERENT components (not just different styles) at different sizes.

Warning: Reimplementing what a CSS media query could do in JavaScript adds unnecessary re-renders and complexity for no real benefit.

Detecting Screen Size in JavaScript with a Hook

When you genuinely need to render different components based on screen size (like a mobile hamburger menu vs. a full desktop nav), a useWindowWidth-style hook tracks the current width in React state, updating on the browser's resize event.

Note: Debounce the resize handler (see the useDebounce pattern from earlier) if you're doing expensive work on every resize event.

Warning: Always remove the resize event listener in the effect's cleanup function, or it leaks with every remount of the component using this hook.

Example: Detecting Screen Size in JavaScript with a Hook

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function useWindowWidth() {
  const [width, setWidth] = React.useState(window.innerWidth);
  React.useEffect(() => {
    const onResize = () => setWidth(window.innerWidth);
    window.addEventListener("resize", onResize);
    return () => window.removeEventListener("resize", onResize);
  }, []);
  return width;
}
function App() {
  const width = useWindowWidth();
  return <p>{width < 768 ? "Mobile layout" : "Desktop layout"}</p>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
  </script>
</body>
</html>

Using matchMedia for a Specific Breakpoint

window.matchMedia(query) checks whether a specific media query currently matches, and can notify your code when that match status changes — a more targeted approach than tracking the raw pixel width when you only care about crossing one specific breakpoint.

Note: matchMedia is often more efficient than a resize listener when you only care about a boolean 'did we cross this one breakpoint' question.

Warning: Remember to remove the matchMedia change listener in cleanup too, exactly like a resize listener.

Example: Using matchMedia for a Specific Breakpoint

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function useIsMobile() {
  const [isMobile, setIsMobile] = React.useState(window.matchMedia("(max-width: 767px)").matches);
  React.useEffect(() => {
    const mql = window.matchMedia("(max-width: 767px)");
    const handler = e => setIsMobile(e.matches);
    mql.addEventListener("change", handler);
    return () => mql.removeEventListener("change", handler);
  }, []);
  return isMobile;
}
function App() {
  const isMobile = useIsMobile();
  return <p>{isMobile ? "Showing mobile nav" : "Showing desktop nav"}</p>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
  </script>
</body>
</html>
Common Mistakes
  1. Trying to detect screen size only once on mount, missing later resize events entirely.
  2. Using JavaScript-based responsive logic for things plain CSS media queries could handle more efficiently.
  3. Forgetting to clean up the resize event listener, leaking it on every remount.
Chapter Summary
  • Most responsive behavior should still come from CSS media queries — React doesn't need to reinvent that.
  • A useWindowWidth-style hook is useful specifically when RENDERING DIFFERENT COMPONENTS (not just different styles) per screen size.
  • The window.matchMedia API lets JavaScript react to a specific media query matching or not.
  • Always clean up resize/matchMedia listeners in useEffect's cleanup function.
Browser Support

matchMedia and resize events are supported in all modern browsers; no specific React version requirement.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.