Why is my CSS ignored? Learn the 9 most common causes, from specificity and load order to caching, invalid selectors and browser quirks.
You change a class, refresh the page, and absolutely nothing happens. So you tweak it again, add `!important`, refresh harder, question your life choices, and now the button is somehow worse. If you’ve been asking why is my CSS ignored, the good news is that CSS usually is not ignoring you out of spite. It is following rules. The annoying part is that there are quite a few of them.
This is one of those front-end problems that feels random until you know what to check. Once you do, debugging becomes much less dramatic and far more boring – which is exactly what you want.
Before blaming specificity, browser bugs, or the moon’s position, make sure the stylesheet is actually loading and the selector matches the element you think it does.
Open DevTools, inspect the element, and look at the Styles panel. If your rule does not appear at all, one of two things is usually true. Either the CSS file is not being loaded, or your selector does not match the element. If the rule appears but is crossed out, that means the browser sees it but another rule is winning.
That simple distinction saves a lot of time. No match and overridden are different problems with different fixes.
This catches beginners and experienced developers alike, because tiny mismatches are easy to miss. Maybe you wrote `.card .title` but the element is actually `.card-title`. Maybe you expected a class on the button, but it sits on the parent. Maybe your selector is targeting an `id` when the markup uses a class.
Pseudo-classes can trip you up too. If you style `input:focus` but the input never receives focus, the rule will never apply. Same idea with `:hover`, `:checked`, `:disabled`, and friends. CSS is literal. It does not grade on intent.
If you are using a framework or component library, inspect the final rendered HTML rather than trusting the source in your head. The DOM often tells a less flattering but more accurate story.
If your rule shows up crossed out in DevTools, specificity is a usual suspect. CSS compares selectors and gives priority to the more specific one. An `id` selector beats a class selector. A long chained selector can beat a shorter one. Inline styles often beat both.
For example, `.btn { background: blue; }` will lose to `.header .actions .btn { background: red; }` if both target the same button and the second rule comes from a loaded stylesheet. That does not mean you should respond by writing `html body main .page .header .actions .btn`. That path leads to pain.
A better fix is usually to simplify the competing selectors or make your styling architecture more predictable. If everything needs a stronger selector to win, the codebase is quietly asking for help.
Yes, `!important` can force a declaration to win. No, it is not automatically evil. It can be reasonable in utility classes, overrides of hostile third-party styles, or accessibility-related cases.
But if your default move is to slap `!important` on every stubborn rule, you are not fixing the problem. You are putting duct tape on the cascade and hoping nobody looks too closely.
When two rules have the same specificity, the one loaded later wins. That means a perfectly valid rule can appear to be ignored simply because another stylesheet comes after it.
This happens a lot when you mix your own styles with a reset, a component library, and page-specific CSS. You think your rule should apply because it looks more relevant. CSS does not care about relevance. It cares about order.
If `main.css` loads before `components.css`, and both define `.alert`, the version in `components.css` wins if specificity is equal. The browser is not making a judgement call. It is just reading from top to bottom.
Sometimes the selector is fine and the file is loaded, but the declaration itself is being dropped. If you write an invalid property or value, the browser ignores it without much ceremony.
A few classic examples: `font-colour` instead of `colour`, `display: hidden`, or `padding: auto`. They read plausibly enough to slip past your eyes but are not valid CSS. The browser shrugs and moves on.
Modern CSS adds another twist. Some properties and values are valid in certain browsers but not all of them, or they need a specific context to work. `gap` in flex layouts used to be patchy. `position: sticky` fails if an ancestor has the wrong overflow settings. `z-index` does nothing on a statically positioned element in most cases. CSS can be technically correct and still not produce the effect you expected.
CSS rules depend on relationships in the DOM. If your selector says `.nav li a` but your links are not inside list items, that selector will never match. If you use child combinators like `>` and the element is nested one level deeper than expected, same issue.
This gets especially messy in templating systems, React components, or CMS output where wrappers appear without warning. You thought the element was a direct child. The actual markup disagrees.
Again, DevTools is the fastest reality check. Not the JSX. Not the template partial. The final DOM.
Sometimes the styles panel says your rule should apply, yet the page still looks wrong. That usually points to layout context, inherited styles, or the dreaded cache.
Caching is a repeat offender. You update `styles.css`, but the browser serves an old version. So now you are debugging yesterday’s code while glaring at today’s file. Hard refresh can help, but during development it is often better to use cache-busting file names or disable cache in DevTools while testing.
Then there is inheritance. You may be changing a property that the element does not inherit, or expecting a parent’s style to force a child into behaving differently than CSS allows. `colour` inherits. `margin` does not. `font-family` usually cascades nicely. `border` very much does not.
Resets and normalisation stylesheets can make your CSS seem ignored when it is actually being neutralised. Component libraries can do the same thing, especially if they apply opinionated base styles to buttons, forms, or headings.
A common example is styling links or form controls and wondering why the browser keeps its own appearance. Some controls have native rendering quirks. Others are being restyled by a library after your CSS loads.
This is where the computed styles panel helps. It shows the final value the browser is using and where it came from. If your `border-radius` is not showing up, the computed tab will usually reveal whether it is overridden, invalid, or simply not visible because of another visual property.
If JavaScript adds inline styles directly on an element, your regular stylesheet rules may lose. Inline styles carry strong priority, and they are common in animation libraries, drag-and-drop tools, and UI frameworks.
For instance, if a script sets `style=”width: 300px”` on an element, your `.panel { width: 100%; }` rule may appear ignored. It is not ignored. It is outranked.
JavaScript can also toggle classes faster than you notice. You apply a style manually, then a script removes the class on render or swaps it during hydration. From your point of view, CSS is broken. From the browser’s point of view, the DOM changed.
If you are using `@layer`, that adds another dimension to the cascade. A rule in one layer can lose to a rule in another layer even when the selector looks stronger than expected. This is useful when done deliberately and baffling when forgotten.
The same goes for custom properties. If `colour: var(–brand-text);` is not working, the issue may not be the `colour` declaration at all. The variable might be undefined in that scope, misspelled, or overridden somewhere higher up.
Modern CSS is powerful, but each new feature gives you one more place to make a perfectly understandable mistake.
When CSS seems ignored, resist the urge to change five things at once. Check one layer at a time. Is the file loaded? Does the selector match? Is the rule crossed out? Is the property valid? Is something more specific or later in the cascade winning? Is JavaScript interfering? Is the browser caching an old file?
That order matters because it keeps you from debugging shadows. Most CSS issues are not mysterious. They are just hidden in plain sight behind the cascade, the DOM, or a framework doing “helpful” things.
Even experienced developers get caught by this stuff. The difference is not magical intuition. It is having a reliable checklist and trusting DevTools more than your memory.
Next time you catch yourself asking why is my CSS ignored, treat it less like a browser tantrum and more like a small investigation. CSS is usually telling the truth. You just have to ask it in the right place.