Why Is My CSS Class Not Applying?

CSS class not applying problems usually happen when the class name does not match, the selector is written wrong, the stylesheet is not loading, or another CSS rule overrides the class.

CSS Debugging Fix

Why is my CSS class not applying?

You add a class to an element, write the CSS, refresh the page, and nothing changes. This is one of the most annoying front-end bugs because the code can look correct at a glance. Most of the time, the class is not applying because of a typo, missing dot, wrong selector, stylesheet loading issue, CSS specificity conflict, or a build/cache problem.

  • Class selector bugs
  • Specificity conflicts
  • Stylesheet loading
  • DevTools debugging

What the bug looks like

You add a class and write CSS for it, but the element keeps the old design, spacing, color, or layout.

Why it happens

The class selector is either not matching, not loading, not winning, or not attached to the element you think it is.

What usually fixes it

Match the class name exactly, use the correct selector, inspect the loaded CSS, and check whether the rule is crossed out.

Error 1

The class name in HTML and CSS does not match

This is the fastest mistake to make and the easiest to miss. CSS class names must match exactly. A missing hyphen or different spelling means the selector never reaches the element.

Broken code

Class mismatch
<div class="hero-card">
  Premium layout
</div>

.herocard {
  background: #fff5ef;
  border-color: #ffd2c2;
}

Broken visual result

Selector misses
Premium layout

The HTML has hero-card, but the CSS targets .herocard.

Unstyled CTA
The browser cannot apply a class rule that does not match the real class name.

Correct code

Class names match
<div class="hero-card">
  Premium layout
</div>

.hero-card {
  background: #fff5ef;
  border-color: #ffd2c2;
}

Fixed visual result

Selector matches
Premium layout

The CSS selector now matches the class used in the HTML.

Styled CTA
Once the class name matches exactly, the rule can reach the element.
Error 2

The selector is missing the class dot

In CSS, a class selector needs a dot. Without it, the browser looks for an HTML element with that name instead of a class. This can make a perfectly good class appear ignored.

Broken code

Missing dot
<button class="cta-button">
  Start fixing
</button>

cta-button {
  background: #ff6a3d;
  color: white;
}

Broken visual result

Browser looks for an element
HTML class: cta-button real
CSS selector: cta-button wrong type
Without the dot, the selector is not targeting a class.

Correct code

Class selector
<button class="cta-button">
  Start fixing
</button>

.cta-button {
  background: #ff6a3d;
  color: white;
}

Fixed visual result

Class selector works
HTML class: cta-button real
CSS selector: .cta-button matches
The dot tells CSS to target elements with that class.
Error 3

The class applies, but a stronger rule overrides it

Sometimes your class is applying, but you still do not see the expected style because another selector wins. In DevTools, your rule may appear crossed out.

Broken code

Specificity conflict
.card {
  background: #fff5ef;
}

.page .content .card {
  background: white;
}

Broken visual result

Class rule crossed out
.card background: #fff5ef overridden
.page .content .card background: white wins
The class exists, but a stronger selector controls the final style.

Correct code

Target intentionally
.content .card {
  background: white;
}

.content .card.is-featured {
  background: #fff5ef;
  border-color: #ffd2c2;
}

Fixed visual result

Intentional selector wins
.content .card base style base
.content .card.is-featured wins
The modifier class is now written to win clearly without random !important.
Error 4

The stylesheet with the class rule is not loading

Your class and selector can both be perfect, but nothing will happen if the CSS file is not loaded on the page. This is common with wrong file paths, stale cache, minified files, or build output that was not regenerated.

Broken code

Missing stylesheet
<link rel="stylesheet" href="/css/layout.css">

/* But the class lives in: */
components/card.css

.card-feature {
  border-color: #ffd2c2;
}

Broken visual result

Rule never loads
/css/layout.css loaded
components/card.css missing
The browser cannot apply CSS from a file it never downloaded.

Correct code

Load the right file
<link rel="stylesheet" href="/css/layout.css">
<link rel="stylesheet" href="/css/components/card.css">

.card-feature {
  border-color: #ffd2c2;
}

Fixed visual result

Rule is available
/css/layout.css loaded
/css/components/card.css loaded
Once the stylesheet loads, the class rule becomes available to the page.
Premium pattern

A production-minded CSS class pattern

A stronger class system keeps names consistent, uses readable modifiers, avoids random specificity battles, and makes component states clear.

Premium code

Clear component classes
<article class="pricing-card pricing-card--featured">
  <h2 class="pricing-card__title">Pro Plan</h2>
  <a class="pricing-card__button" href="#">Start now</a>
</article>

.pricing-card {
  border: 1px solid #e5e7eb;
  border-radius: 24px;
  background: white;
}

.pricing-card--featured {
  border-color: #ffd2c2;
  box-shadow: 0 18px 38px rgba(255,106,61,.12);
}

.pricing-card__button {
  background: #ff6a3d;
  color: white;
}

Premium visual result

Classes describe the component
Pro Plan

The class names are consistent, readable, and connected to the component they style.

Start now
Premium class naming makes debugging easier because the HTML and CSS tell the same story.

Fast practical rule

If a CSS class is not applying, inspect the element in DevTools. First confirm the class exists in the HTML. Then confirm the selector appears in the Styles panel. If it appears crossed out, you have a specificity or order problem. If it does not appear, you have a selector, file, or cache problem.

Debug checklist

  • Check the HTML class name and CSS selector spelling character by character.
  • Make sure class selectors start with a dot, like .card.
  • Inspect the element and confirm the class is really present in the DOM.
  • Check whether your CSS rule appears in DevTools.
  • If the rule is crossed out, check specificity and CSS order.
  • If the rule does not appear, check whether the stylesheet is loaded.
  • Clear cache or rebuild assets if you recently changed the CSS file.
  • Avoid using !important until you know why the class is losing.
Best first move Inspect the element and confirm whether the class exists in the rendered DOM.
Most common cause A tiny mismatch between the HTML class name and the CSS selector.
Most misleading cause The class is applying, but a stronger selector overrides it.
Better mindset A class not applying is not a guessing game. DevTools can show whether the problem is matching, loading, or winning.

Final takeaway

A CSS class not applying usually means one of three things: the selector does not match, the stylesheet is not loading, or another rule is winning. Once you identify which one it is, the fix becomes simple.

Start in DevTools. Confirm the class exists, confirm the rule appears, and confirm whether it is active or crossed out. That gives you a real answer instead of turning the stylesheet into a pile of random overrides.

Want more fixes like this?

Browse more CSS debugging guides or jump to the full FrontFixer library.

Why Is My Hover Effect Not Working?

A hover effect usually stops working when the selector does not match the element, another layer is blocking the pointer, a stronger CSS rule overrides the hover state, or the device does not actually support hover.

CSS Interaction Fix

Why is my hover effect not working?

A hover effect can fail in several sneaky ways. The button may not change color, the card may not lift, the dropdown may not open, or the effect may work on desktop but feel broken on mobile. The problem is usually not “hover is broken.” The real issue is selector targeting, CSS order, specificity, pointer events, overlays, disabled elements, or touch-screen behavior.

  • Hover selector bugs
  • Pointer events
  • CSS specificity
  • Touch devices

What the bug looks like

The button does not change color, the card does not lift, the menu does not open, or the hover works only when your mouse is over a tiny part of the element.

Why it happens

The hover rule is either not matching, not winning, not receiving pointer input, or being tested on a device where hover does not behave normally.

What usually fixes it

Confirm the selector, inspect the active rule, remove blocking layers, add transitions to the base state, and design a touch-friendly fallback.

Error 1

The hover selector targets the wrong element

This is the simplest hover bug. The CSS is valid, but the selector does not match the element you are actually hovering. The browser is doing exactly what you asked. It is just not the element you meant.

Broken code

Wrong selector
<a class="cta-button" href="#">
  Start fixing
</a>

.button:hover {
  background: #ff6a3d;
  color: white;
}

Broken visual result

Hover rule never matches
CTA area The button class is cta-button, but the CSS is targeting .button:hover. Start fixing
The hover effect looks broken because the selector and the HTML class do not match.

Correct code

Matching selector
<a class="cta-button" href="#">
  Start fixing
</a>

.cta-button:hover {
  background: #ff6a3d;
  color: white;
}

Fixed visual result

Hover rule matches
CTA area The selector now targets the same class that exists in the HTML. Start fixing
The effect appears because the hover rule is attached to the correct element.
Error 2

A later CSS rule overrides the hover effect

Sometimes the hover selector is correct, but it still loses. The hover state may be crossed out in DevTools because a later rule or stronger selector keeps the old color, transform, or opacity.

Broken code

Hover loses cascade
.card:hover {
  transform: translateY(-4px);
  background: #fff5ef;
}

.featured-card {
  transform: none;
  background: white;
}

Broken visual result

Hover is overridden
.card:hover transform: translateY(-4px) overridden
.featured-card transform: none wins
The hover rule exists, but another rule wins the final computed style.

Correct code

Hover wins intentionally
.featured-card {
  background: white;
  transition: transform .2s ease, background .2s ease;
}

.featured-card:hover {
  transform: translateY(-4px);
  background: #fff5ef;
}

Fixed visual result

Hover wins
.featured-card base style base
.featured-card:hover transform active
The hover state now targets the same component and appears after the base style.
Error 3

An invisible overlay blocks the hover target

This is a sneaky one. An absolutely positioned layer, pseudo-element, or overlay can sit above the button. Your mouse is technically hovering the overlay, not the button underneath.

Broken code

Overlay steals pointer
.card::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 2;
}

.card .button {
  position: relative;
  z-index: 1;
}

Broken visual result

Pointer hits overlay
Card content The button looks visible, but another layer is sitting above it. Hover me
Invisible overlay blocks hover
The hover target is visually there, but it is not receiving the pointer.

Correct code

Overlay ignores pointer
.card::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.card .button {
  position: relative;
  z-index: 2;
}

Fixed visual result

Button receives hover
Card content The decorative layer is still there, but it no longer steals pointer input. Hover me
Overlay no longer blocks
Use pointer-events:none only on decorative layers that should not be interactive.
Error 4

The hover effect is being tested on a touch device

Mobile devices do not have a mouse cursor hovering above the screen. Some browsers simulate hover after a tap, some do not, and some leave hover-like states stuck. A hover-only interaction is not a safe mobile pattern.

Broken code

Hover-only UI
.menu {
  display: none;
}

.nav:hover .menu {
  display: block;
}

Broken visual result

Touch has no real hover
Mobile menu The menu depends only on hover, so it may not open reliably on phones. Menu
Hover can be a nice desktop enhancement, but it should not be the only way to reveal important content.

Correct code

Hover plus focus
.menu {
  display: none;
}

.nav:hover .menu,
.nav:focus-within .menu {
  display: block;
}

.nav-toggle {
  cursor: pointer;
}

Fixed visual result

Keyboard and tap friendlier
Mobile menu The interaction now supports hover and focus, making it less fragile. Menu
For serious mobile navigation, JavaScript state is often more reliable than hover-only behavior.
Premium pattern

A production-minded hover pattern

The stronger pattern treats hover as progressive enhancement. The base state works. The focus state works. Touch users are not blocked. Motion is smooth, but not required for the interface to make sense.

Premium code

Hover, focus, motion-safe
.card {
  position: relative;
  border: 1px solid #e5e7eb;
  border-radius: 24px;
  background: #fff;
  transition:
    transform .2s ease,
    border-color .2s ease,
    box-shadow .2s ease;
}

.card:hover,
.card:focus-within {
  transform: translateY(-3px);
  border-color: #ffd2c2;
  box-shadow: 0 18px 38px rgba(255,106,61,.12);
}

.card::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

@media (hover: none) {
  .card:hover {
    transform: none;
  }
}

Premium visual result

Hover is enhancement
Production-ready card

The component has a good base state, a hover state, a focus state, and a safer touch-device fallback.

Open fix
Premium hover is not just pretty. It is predictable, accessible, and less likely to break across devices.

Fast practical rule

If a hover effect is not working, inspect the element and force the :hover state in DevTools. If the rule appears but is crossed out, fix specificity or order. If the rule never appears, fix the selector. If the element never receives hover, check overlays and pointer events.

Debug checklist

  • Confirm the hover selector matches the actual class or element in the HTML.
  • Use DevTools to force :hover and see whether the rule becomes active.
  • Check whether the hover rule is crossed out by a later or stronger selector.
  • Check whether an overlay, pseudo-element, or absolute layer is sitting above the target.
  • Use pointer-events:none only on decorative layers that should not receive input.
  • Make sure transitions are placed on the base element, not only on the hover state.
  • Do not rely on hover-only behavior for important mobile interactions.
  • Add :focus or :focus-within when the element should also work by keyboard or tap.
Best first move Force :hover in DevTools before changing random CSS.
Most common cause The selector does not match the element you are actually hovering.
Most invisible cause An overlay or pseudo-element is sitting above the button and stealing the pointer.
Better mindset Hover should improve the interface, not be the only way the interface works.

Final takeaway

A hover effect not working usually has a concrete cause: the selector is wrong, the rule is overridden, the element is not receiving pointer input, or the device does not support hover the way a desktop mouse does.

Start by forcing :hover in DevTools. Then check whether the rule matches, whether it wins, and whether another layer is blocking the target. Once those three questions are answered, the fix becomes much easier.

Want more fixes like this?

Browse more CSS interaction and layout debugging guides in the FrontFixer library.

Why Is My CSS Not Updating After I Change It?

CSS not updating after you change it usually means the browser is still reading an old file, a different stylesheet, or a stronger CSS rule than the one you just edited.

CSS Debugging Fix

Why is my CSS not updating after I change it?

You change the CSS, save the file, refresh the page, and nothing happens. The button keeps the old color. The card still has the old spacing. The mobile layout still looks broken. In most real projects, the problem is not that CSS is ignoring you. The problem is usually cache, file order, specificity, the wrong stylesheet, minified assets, or a build process that has not generated the new file yet.

  • CSS cache
  • Wrong stylesheet
  • Specificity conflicts
  • WordPress debugging

What the bug looks like

You change a color, margin, font size, layout rule, or mobile style, but the visible page keeps showing the old design.

Why it happens

The page is either loading old CSS, loading a different CSS file, or applying a stronger rule after your new rule.

What usually fixes it

Hard refresh, clear cache, confirm the loaded file in DevTools, inspect the rule, then fix specificity, order, or the build pipeline.

Error 1

The browser is still loading the cached stylesheet

This is the classic reason CSS changes do not show. You saved the file, but the browser already has an older version stored. So the code is changed on the server, while your screen still shows yesterday’s CSS.

Broken code

Old cached file
<link rel="stylesheet" href="/assets/style.css">

/* You changed this today */
.hero-card {
  border-radius: 24px;
  background: white;
}

Broken visual result

Old CSS still visible
Old header style
Old card shape The page still looks like the previous version because the cached file is being used.
The CSS file was changed, but the browser did not request a fresh copy.

Correct code

Cache-busted file
<link rel="stylesheet"
      href="/assets/style.css?v=2026-06-06">

/* New version now reaches the browser */
.hero-card {
  border-radius: 24px;
  background: white;
}

Fixed visual result

Fresh CSS loaded
Updated header style
New card shape The browser now loads the newer file, so the visual update finally appears.
Versioning the file URL forces the browser to request the updated stylesheet.
Error 2

A stronger selector overrides the CSS you changed

Sometimes the CSS is updating, but your rule is losing. In DevTools, the new property may appear crossed out because a more specific selector, inline style, or later rule is winning the cascade.

Broken code

Weak selector loses
.button {
  background: #ff6a3d;
}

/* Later or stronger rule */
.header .button {
  background: #0f172a;
}

Broken visual result

New rule crossed out
.button background: #ff6a3d overridden
.header .button background: #0f172a wins
The file updated, but the rule you edited is not the rule controlling the final button style.

Correct code

Target the real selector
.header .button {
  background: #ff6a3d;
}

.header .button:hover {
  background: #eb5628;
}

Fixed visual result

Correct rule wins
.header .button background: #ff6a3d active
.header .button:hover background: #eb5628 ready
The update works because the rule now matches the selector that actually controls the element.
Error 3

You edited a file the page is not loading

This one feels ridiculous until it happens. The CSS file you edited may not be the CSS file loaded by the page. WordPress themes, child themes, page builders, minified assets, and build tools can all create this confusion.

Broken code

Wrong file edited
/* You edited this file */
themes/frontfixer/style.css

.card {
  padding: 28px;
}

/* But the page actually loads */
uploads/cache/minified-style.css

Broken visual result

Wrong source file
themes/frontfixer/style.css edited
uploads/cache/minified-style.css loaded
Your code changed, but not in the file that the browser is currently using.

Correct code

Confirm loaded source
/* In DevTools, check the rule source */
.card {
  padding: 28px;
}

/* Then edit the real source or purge/rebuild */
Loaded file:
style.css?ver=2026-06-06

Fixed visual result

Right file confirmed
style.css?ver=2026-06-06 loaded
.card padding: 28px active
DevTools tells you the exact stylesheet and line where the winning rule is coming from.
Error 4

WordPress cache or optimization is serving old CSS

In WordPress, your CSS may be correct but still not visible because an optimization plugin, server cache, CDN cache, or minified file is serving an older generated version. This is common after editing Custom CSS, theme files, or page-level HTML/CSS.

Broken setup

Old optimized CSS
Original CSS changed:
.card {
  border-radius: 24px;
}

/* But the front-end still loads */
combined.min.css
cached by plugin/CDN/server

Broken visual result

Optimized file is stale
Cached version
Old minified CSS The page is still using a generated file that has not been refreshed.
Clearing only the browser cache may not be enough if the server or plugin is serving old CSS.

Correct workflow

Purge and rebuild
After editing CSS:

1. Save the post/theme/CSS file
2. Purge plugin cache
3. Purge server/CDN cache if used
4. Regenerate/minify CSS if needed
5. Hard refresh the browser

Fixed visual result

Fresh optimized CSS
Updated version
New generated file The optimized CSS has been rebuilt, so the live page finally matches your edit.
For WordPress sites, always think in layers: browser cache, plugin cache, server cache, CDN cache.
Premium pattern

A production-minded CSS update workflow

The stronger fix is not just refreshing harder. A reliable workflow makes CSS updates predictable: version your stylesheet, inspect the winning rule, avoid random specificity wars, and use a clear cache purge routine after important changes.

Premium workflow

Predictable updates
<link rel="stylesheet"
      href="/assets/style.css?v=2026-06-06">

/* Keep selectors intentional */
.ffx-card {
  padding: clamp(18px, 3vw, 28px);
  border-radius: 24px;
}

/* Avoid random emergency overrides */
.ffx-card.is-featured {
  border-color: #ffd2c2;
  box-shadow: 0 18px 38px rgba(255,106,61,.12);
}

/* After deploying:
   hard refresh, inspect source,
   purge cache, then request indexing
   for important updated pages. */

Premium visual result

Clean update path
Production-ready CSS
Predictable visual update The stylesheet is versioned, the selector is intentional, and the cache workflow is clear.
The premium version does not rely on panic-refreshing. It makes the CSS pipeline easier to trust.

Fast practical rule

If CSS is not updating, do not immediately add !important. First check whether the browser is loading the new file at all. Then inspect the exact rule in DevTools. If the file is old, fix cache. If the rule is crossed out, fix specificity or order.

Debug checklist

  • Hard refresh the page with the browser cache bypassed.
  • Open DevTools and confirm the stylesheet URL actually changed or loaded fresh.
  • Inspect the element and check whether your rule is active or crossed out.
  • Confirm you edited the stylesheet that the page is really loading.
  • Check whether a later rule overrides your new rule.
  • Check selector specificity before using !important.
  • Clear WordPress plugin cache, server cache, CDN cache, and minified CSS when relevant.
  • If your project uses a build process, rebuild the compiled CSS file.
  • Test in an incognito window or another browser to separate browser cache from server cache.
Best first move Inspect the element in DevTools and check whether your new rule appears at all.
Most common cause Browser, plugin, CDN, or server cache is still serving an older CSS file.
Most misleading cause The CSS changed, but another selector is stronger, so the visual result stays the same.
Better mindset CSS debugging is not guessing. It is proving which file loaded and which rule won.

Final takeaway

CSS not updating is usually not a mystery. The page is either loading an old stylesheet, loading a different stylesheet, or applying a different rule than the one you edited. Once you separate those three possibilities, the bug becomes much easier to fix.

Start with DevTools. Confirm the file. Confirm the selector. Confirm the winning rule. Then clear or rebuild the cache only where needed. That is faster than stacking random overrides until the stylesheet becomes harder to maintain.

Want more fixes like this?

Browse more CSS debugging guides or jump to the full FrontFixer library.

Why Is My Media Query Not Working?

Media query not working problems usually happen when the browser is reading a different viewport, a different CSS rule, or a more rigid layout than the one you think you are testing.

Responsive CSS Fix

Why is my media query not working?

If your mobile styles are not applying, your breakpoint seems ignored, or your layout stays stuck in desktop mode, the browser is usually not being random. The real issue is usually a missing viewport tag, invalid syntax, CSS order, specificity, cache, or a rigid layout that makes the media query look broken even when it is actually firing.

  • Viewport setup
  • Breakpoint logic
  • CSS cascade
  • Rigid layout traps

What the bug looks like

Your CSS says mobile should be one column, but the page stays in desktop mode. Or your media query changes one thing, but the layout still overflows and looks broken.

Why it happens

A media query does not magically make a layout responsive. It only applies CSS under a condition. If setup, cascade, or structure is wrong, the result still breaks.

What usually fixes it

Confirm the viewport tag, test the breakpoint in DevTools, inspect overridden rules, then replace rigid layout rules with flexible responsive patterns.

Error 1

Missing viewport tag makes mobile CSS look ignored

This is one of the most common reasons a media query does not work on mobile. Without the viewport meta tag, the browser may render the page as a wide desktop canvas and scale it down. Your breakpoint may not match the real screen the way you expect.

Broken code

Missing viewport
<head>
  <title>My Page</title>
  <link rel="stylesheet" href="style.css">
</head>

@media (max-width: 768px) {
  .cards {
    grid-template-columns: 1fr;
  }
}

Broken visual result

Mobile acts like desktop
Card 1
Card 2
Card 3
The page is still behaving like a wide desktop canvas, so the mobile layout feels ignored.

Correct code

Real mobile viewport
<head>
  <meta name="viewport"
        content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="style.css">
</head>

@media (max-width: 768px) {
  .cards {
    grid-template-columns: 1fr;
  }
}

Fixed visual result

Viewport matches device
Card 1
Card 2
Card 3
The browser now treats the screen as a real mobile viewport, so the breakpoint can behave correctly.
Error 2

Invalid media query syntax silently breaks the rule

Media query syntax is easy to almost get right. A missing space, missing unit, wrong parenthesis, or forgotten brace can make the browser skip the rule or read it differently than you intended.

Broken code

Syntax trap
@media screen and(max-width: 768px) {
  .menu {
    display: none;
  }

  .cards {
    grid-template-columns: 1fr;
  }
}

Broken visual result

Breakpoint ignored
Desktop nav still visible
Card
Card
Card
The CSS looks close, but the condition is malformed, so the mobile rule does not behave as expected.

Correct code

Valid condition
@media screen and (max-width: 768px) {
  .menu {
    display: none;
  }

  .cards {
    grid-template-columns: 1fr;
  }
}

Fixed visual result

Mobile rule applies
Compact mobile header
Card 1
Card 2
Card 3
The same layout now stacks because the media query condition is valid and readable.
Error 3

The media query works, but CSS order overrides it

The browser may be applying your media query correctly, then immediately replacing it with a later rule. This is why media queries can “work” in DevTools but still not change what you see on the page.

Broken code

Later desktop rule wins
@media (max-width: 768px) {
  .card-title {
    font-size: 18px;
  }
}

.card-title {
  font-size: 36px;
}

Broken visual result

Mobile rule crossed out

Huge title on mobile

The media query fires, but the later desktop rule wins the cascade.

@media font-size: 18pxoverridden
later font-size: 36pxwins

Correct code

Mobile rule comes after
.card-title {
  font-size: 36px;
}

@media (max-width: 768px) {
  .card-title {
    font-size: 22px;
  }
}

Fixed visual result

Mobile rule wins

Readable mobile title

The mobile rule appears later, so the cascade now matches the responsive intention.

base font-size: 36pxbase
@media font-size: 22pxwins
Error 4

The breakpoint fires, but the layout is still rigid

This is the grown-up version of the media query bug. The media query is not dead. The layout is still too rigid. A fixed-width wrapper, a wide grid, a long code block, or an image without responsive limits can make the page look broken even after the breakpoint activates.

Broken code

Breakpoint fires, layout still breaks
.wrapper {
  width: 1200px;
}

.cards {
  display: grid;
  grid-template-columns: repeat(3, 320px);
}

@media (max-width: 768px) {
  .cards {
    grid-template-columns: 1fr;
  }
}

Broken visual result

The wrapper is still 1200px
Mobile breakpoint active
Wide wrapper
Still overflowing
Not responsive
The media query changed the grid, but the parent still forces a desktop width.

Correct code

Flexible parent and grid
.wrapper {
  width: min(100%, 1200px);
  margin-inline: auto;
  padding-inline: 16px;
}

.cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
}

@media (max-width: 768px) {
  .cards {
    grid-template-columns: 1fr;
  }
}

Fixed visual result

Parent can shrink
Responsive layout
Card 1
Card 2
Card 3
Now the wrapper and grid both cooperate with the breakpoint.
Premium pattern

A production-minded media query setup

The best responsive fix is not just one media query. It is a layout system that starts flexible, uses safe grid tracks, lets children shrink, protects images, and only uses breakpoints to adjust behavior—not to rescue broken desktop code.

Premium code

Flexible first
.layout {
  width: min(100%, 1120px);
  margin-inline: auto;
  padding-inline: clamp(16px, 4vw, 32px);
}

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: clamp(16px, 3vw, 28px);
}

.card,
.card * {
  min-width: 0;
}

.card img {
  display: block;
  max-width: 100%;
  height: auto;
}

@media (max-width: 768px) {
  .layout {
    padding-inline: 16px;
  }

  .card-title {
    font-size: clamp(24px, 8vw, 34px);
  }
}

Premium visual result

Flexible before breakpoint
Production-ready cards
Safe card width
No overflow trap
Breakpoint becomes lighter
The layout is responsive even before the media query has to do heavy work.

Fast practical rule

If your media query is not working, do not start by changing random breakpoint numbers. First confirm the viewport tag, then test whether the rule is firing in DevTools, then check whether another rule or a rigid parent is still winning.

Debug checklist

  • Confirm the page includes <meta name="viewport" content="width=device-width, initial-scale=1">.
  • Resize the page in DevTools and confirm whether the media query is actually firing.
  • Check the media query syntax for missing spaces, braces, parentheses, units, and invalid conditions.
  • Inspect whether a later CSS rule is overriding the media query.
  • Check whether a stronger selector is beating your mobile selector.
  • Verify whether the breakpoint should use max-width or min-width.
  • Look for a fixed-width wrapper, wide grid track, long word, code block, image, table, or child element that refuses to shrink.
  • Clear browser, plugin, and CDN cache if your CSS changes are not showing at all.
Best first move Use DevTools to see whether the media query is active before changing the breakpoint value.
Most overlooked cause The viewport tag is missing, so the browser never behaves like the real mobile screen.
Most frustrating cause The media query works, but a later CSS rule silently overrides it.
Better mindset Media queries should tune a flexible layout, not save a layout that was built rigid from the beginning.

Final takeaway

A media query not working rarely means the browser is broken. Most of the time, the browser is following the rules exactly: the viewport is wrong, the condition is invalid, the cascade is overriding the rule, specificity is too strong, cache is stale, or the layout is still too rigid to respond.

Start by proving whether the media query is active. Then debug the cascade. Then fix the structure. Once the layout is flexible first, media queries become precise adjustments instead of emergency rescue patches.

Want more fixes like this?

Browse more responsive debugging guides or jump to the full FrontFixer library.