When text-decoration: none seems not to work, it is usually because a more specific rule overrides it, the element inherits differently than expected, or the browser applies default user-agent styles that reappear later in the cascade. This guide explains how specificity, inheritance, source order, and pseudo-classes affect text decoration, shows how to inspect and fix common causes, and provides robust patterns that work across modern browsers.
How CSS specificity and source order affect text-decoration
Specificity determines which declarations win when multiple rules target the same element. A selector with higher specificity will override text-decoration: none if it appears earlier or is less specific. Inspect the computed styles in DevTools to see which rule is winning and from where. Increasing specificity, adding an additional selector, or moving your rule after conflicting rules in the stylesheet can resolve the issue.
Selector specificity and the cascade
Classes and attributes beat types, IDs beat classes, and inline styles beat IDs unless !important is used. If an external stylesheet or user-agent sets a { text-decoration: underline; } and your internal stylesheet has lower priority or loads earlier, the underline can reappear. Use DevTools to review the source order and specificity bars to identify the conflicting declaration.
Common specificity pitfalls
- Rules loaded earlier are overridden by later, equally specific rules.
- Multiple classes increase specificity more than repeated type selectors.
- Nested selectors in preprocessors can quietly raise specificity beyond what you expect.
How inheritance and element defaults influence text decoration
Text decoration is not inherited by default in CSS, but it applies to the text of an element and any inline-level children. If you set text-decoration: none on a block container, inline text and spans inside will show no decoration unless a more specific rule targets them directly or pseudo-classes like :hover add it back.
Decoration on inline vs block elements
Only inline-level elements and text nodes render decoration; applying text-decoration: none to a block box will not remove underlines from links inside unless the link itself is targeted. Make sure you are styling the correct element in the chain: context matters.
User agent stylesheets and normalization
Browsers apply default decoration to links and certain form controls. A common pattern is user agent stylesheet { a { text-decoration: underline; } } that can persist if your rule is not specific enough. Reset or normalize user-agent styles with a base rule that explicitly targets the elements you control.
Debugging steps for text-decoration none not working
Use a systematic approach to diagnose why text-decoration: none appears ineffective. Start with the simplest checks and move toward deeper specificity and inheritance issues. This workflow helps you quickly pinpoint the cause without guesswork.
- Check DevTools computed styles for the element and locate the struck-through declaration.
- Verify that your selector specificity is high enough to win.
- Inspect whether a pseudo-class such as
:hoveror:activeis adding decoration later in the cascade. - Look for JavaScript or frameworks that may manipulate class names or inline styles at runtime.
- Confirm the rule is not overridden by an
!importantexception elsewhere.
Authoritative reference data for expected behavior
Understanding baseline expectations from specifications and common implementation patterns reduces confusion when behavior differs.
| Attribute / Property | Verified Detail | Source Type |
|---|---|---|
text-decoration initial value | none (computed as none per spec, but user-agent may add underline) | CSS Text Decoration Module Level 3 |
| Inheritance | does not inherit by default; applies to text and inline-level children | CSS Text Decoration Module Level 3 |
| Applies to | inline-level elements and text content | CSS Visual Format Model |
| Specificity comparison examples | type = 0,0,0,1; class = 0,0,1,0; ID = 0,1,0,0 | CSS Selectors Level 3 |
| User-agent default for <a> | typically underline unless overridden | Common browser engines (consistent across Chrome, Firefox, Safari) |
Practical fixes and reliable patterns
Once you understand the cause, apply fixes that align with maintainability and performance. Prefer increasing specificity thoughtfully, avoid !important when unnecessary, and scope styles to the elements that truly need them.
Working examples
- Ensure your rule targets the same element or pseudo-state as the competing rule.
- Use the browser’s specificity calculator or DevTools strikethrough indicators to compare selectors.
- Move custom styles after framework or library styles or increase specificity with an additional class.
- When necessary, apply
text-decoration: none !importantonly as a last resort and document why.
Interaction with pseudo-classes and states
Pseudo-classes such as :hover, :focus, and :active can add decoration if they appear after your base rule. To remove decoration in all states, either cover all relevant pseudo-classes or use a single rule that targets the element regardless of state, provided specificity is sufficient.
Framework and component-library considerations
Component libraries often set their own decoration rules with high-specificity selectors or scoped styles. In those environments, use the library’s APIs for theming or override decoration with locally scoped classes that are correctly ordered and specific.
Accessibility and usability implications
Underlines on links provide essential visual cues for keyboard and mouse users. Removing text decoration should be intentional and compensated with other visible indicators to maintain clarity about interactive text. Preserve or replicate affordances when design systems deviate from defaults.
Summary and best practices
To reliably make text-decoration: none work, target the right element with sufficient specificity, ensure your rule appears after competing declarations, and account for pseudo-classes and user-agent defaults. Inspect computed styles to confirm which declarations are active, and prefer clear, maintainable selectors over heavy-handed overrides.