Common Mistakes
Fixed widths, pixel assumptions, forgotten touch targets, ignoring landscape, and other responsive pitfalls. You'll hit this when a button is too small to tap on a phone or a layout collapses in landscape mode.
.container {
width: 960px;
margin: 0 auto;
}.container {
width: 960px;
margin: 0 auto;
}.container {
width: min(100% - 2rem, 960px);
margin-inline: auto;
}.container {
width: min(100% - 2rem, 960px);
margin-inline: auto;
}A fixed 960px container overflows on any screen narrower than 960px. On a 375px phone, you get a horizontal scrollbar and nearly two-thirds of the content is off-screen. Never use fixed pixel widths for layout containers.
min(100% - 2rem, 960px) caps at 960px on large screens but shrinks to fit on small screens with 1rem padding on each side. One line, no media queries, no horizontal overflow. margin-inline: auto is the logical property equivalent.
<IconButton size="small" sx={{ p: 0.5 }}>
<CloseIcon sx={{ fontSize: 16 }} />
</IconButton>
{/* Renders as ~24px tap target */}<IconButton size="small" sx={{ p: 0.5 }}>
<CloseIcon sx={{ fontSize: 16 }} />
</IconButton>
{/* Renders as ~24px tap target */}<IconButton
size="small"
sx={{ minWidth: 44, minHeight: 44 }}
>
<CloseIcon sx={{ fontSize: 16 }} />
</IconButton>
{/* Visual is small, tap target is 44px */}<IconButton
size="small"
sx={{ minWidth: 44, minHeight: 44 }}
>
<CloseIcon sx={{ fontSize: 16 }} />
</IconButton>
{/* Visual is small, tap target is 44px */}A 24px tap target is frustrating on touch devices because users miss the button and accidentally tap adjacent elements. Apple's HIG recommends 44pt, Google Material recommends 48dp. Small visual elements need padding to reach the minimum.
WCAG recommends at least 44x44px touch targets. Setting minWidth/minHeight on the button keeps the visual compact while making the clickable area finger-friendly. The icon stays 16px but the touch area is 44px.
<head>
<title>My App</title>
<meta charSet="utf-8" />
</head><head>
<title>My App</title>
<meta charSet="utf-8" />
</head><head>
<title>My App</title>
<meta charSet="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1"
/>
</head><head>
<title>My App</title>
<meta charSet="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1"
/>
</head>Without <meta name="viewport">, mobile browsers assume the page is a desktop site and render it at 980px wide, then zoom out. Media queries based on min-width: 768px fire even on a 375px phone because the layout viewport is 980px.
Without the viewport meta tag, mobile browsers render the page at ~980px wide and zoom out to fit. width=device-width tells the browser to use the actual device width, enabling your media queries and responsive CSS to work correctly.
.mobile-layout {
padding-top: env(safe-area-inset-top);
}
/* Only considers portrait mode */
@media (max-width: 768px) {
.sidebar { display: none; }
}.mobile-layout {
padding-top: env(safe-area-inset-top);
}
/* Only considers portrait mode */
@media (max-width: 768px) {
.sidebar { display: none; }
}.mobile-layout {
padding-top: env(safe-area-inset-top);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
/* Consider landscape phones */
@media (max-height: 500px) and (orientation: landscape) {
.header { position: static; }
.hero { min-height: auto; }
}.mobile-layout {
padding-top: env(safe-area-inset-top);
padding-left: env(safe-area-inset-left);
padding-right: env(safe-area-inset-right);
}
/* Consider landscape phones */
@media (max-height: 500px) and (orientation: landscape) {
.header { position: static; }
.hero { min-height: auto; }
}Only applying safe-area-inset-top ignores landscape mode where the notch is on the side. A max-width: 768px breakpoint doesn't account for a phone in landscape (which might be 812px wide). Test both orientations.
Landscape phones have very little vertical space (~320px). A sticky header + full-height hero can leave zero room for content. Safe area insets on left/right handle the notch in landscape. Always test your layout rotated.
// "iPhones are 375px wide"
const MOBILE_WIDTH = 375;
function useLayout() {
const width = useWindowWidth();
if (width <= MOBILE_WIDTH) return "phone";
if (width <= 768) return "tablet";
return "desktop";
}// "iPhones are 375px wide"
const MOBILE_WIDTH = 375;
function useLayout() {
const width = useWindowWidth();
if (width <= MOBILE_WIDTH) return "phone";
if (width <= 768) return "tablet";
return "desktop";
}// Use CSS for visual changes
<Box
sx={{
display: "grid",
gridTemplateColumns: {
xs: "1fr",
sm: "1fr 1fr",
md: "250px 1fr",
},
}}
>
{/* Layout adapts to content needs */}
</Box>// Use CSS for visual changes
<Box
sx={{
display: "grid",
gridTemplateColumns: {
xs: "1fr",
sm: "1fr 1fr",
md: "250px 1fr",
},
}}
>
{/* Layout adapts to content needs */}
</Box>375px covers some iPhones, but the iPhone 12-14 are 390px, the 14 Pro is 393px, and the 16 Pro Max is 440px. Galaxy phones range from 360-412px. Pixel assumptions become wrong with every new device release. Design for content breakpoints, not device widths.
Device pixel widths are arbitrary and constantly changing. iPhones range from 320px (SE 1st gen) to 440px (16 Pro Max), and Android phones vary even more. Instead of mapping widths to device categories, use CSS layouts that adapt fluidly. Breakpoints should be based on *content needs*, not device brands.