惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Archives - TechRepublic
Security Archives - TechRepublic
P
Privacy & Cybersecurity Law Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
W
WeLiveSecurity
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
L
LINUX DO - 热门话题
C
Cybersecurity and Infrastructure Security Agency CISA
S
Security Affairs
Latest news
Latest news
Security Latest
Security Latest
N
News and Events Feed by Topic
Spread Privacy
Spread Privacy
P
Proofpoint News Feed
T
The Blog of Author Tim Ferriss
Y
Y Combinator Blog
Google DeepMind News
Google DeepMind News
www.infosecurity-magazine.com
www.infosecurity-magazine.com
T
The Exploit Database - CXSecurity.com
The Last Watchdog
The Last Watchdog
C
Cyber Attacks, Cyber Crime and Cyber Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
V
Vulnerabilities – Threatpost
Hacker News - Newest:
Hacker News - Newest: "LLM"
Microsoft Azure Blog
Microsoft Azure Blog
V
Visual Studio Blog
The Cloudflare Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
G
GRAHAM CLULEY
博客园_首页
S
Secure Thoughts
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
AWS News Blog
AWS News Blog
腾讯CDC
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Register - Security
The Register - Security
N
News and Events Feed by Topic
A
Arctic Wolf
MongoDB | Blog
MongoDB | Blog
爱范儿
爱范儿
Project Zero
Project Zero
A
About on SuperTechFans
罗磊的独立博客
云风的 BLOG
云风的 BLOG
Know Your Adversary
Know Your Adversary
S
Security @ Cisco Blogs
Google Online Security Blog
Google Online Security Blog
K
Kaspersky official blog
L
LINUX DO - 最新话题
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
F
Fortinet All Blogs

CSS Wizardry

Front-End’s Missing Metric: The TBT Window Meet Your Users Where They Are with Obs.js Better Browser Caching with No-Vary-Search font-family Doesn’t Fall Back the Way You Think What Is CSS Containment and How Can I Use It? When All You Can Do Is All or Nothing, Do Nothing Obs.js: Context-Aware Web Performance for Everyone Low- and Mid-Tier Mobile for the Real World (2025) The Fastest Site in the Tour de France Making Sense of the Performance Extensibility API Why Do We Have a Cache-Control Request Header? HTML Is Not a Programming Language… Build for the Web, Build on the Web, Build with the Web Licensing Code on CSS Wizardry A Layered Approach to Speculation Rules Designing (and Evolving) a New Web Performance Score Core Web Vitals Colours The Ultimate Contract Templates for Tech Consultants: Protect Your Business and Get Paid Optimising for High Latency Environments Cache Grab: How Much Are You Leaving on the Table? blocking=render: Why would you do that?! Correctly Configure (Pre) Connections The Three Cs: 🤝 Concatenate, 🗜️ Compress, 🗳️ Cache What Is the Maximum max-age? How to Clear Cache and Cookies on a Customer’s Device The Ultimate Low-Quality Image Placeholder Technique Core Web Vitals for Search Engine Optimisation: What Do We Need to Know? The HTTP/1-liness of HTTP/2 In Defence of DOM­Content­Loaded Site-Speed Topography Remapped Why Not document.write()? Speeding Up Async Snippets Critical CSS? Not So Fast! Measure What You Impact, Not What You Influence Optimising Largest Contentful Paint Measuring Web Performance in Mobile Safari Site-Speed Topography Speed Up Google Fonts Real-World Effectiveness of Brotli Performance Budgets, Pragmatically Lazy Pre-Browsing with Prefetch Making Cloud.typography Fast(er) Time to First Byte: What It Is and How to Improve It Self-Host Your Static Assets Tips for Technical Interviews Cache-Control for Civilians Bandwidth or Latency: When to Optimise for Which ITCSS × Skillshare What If? CSS and Network Performance The Three Types of Performance Testing Getting to Know a Legacy Codebase Image Inconsistencies: How and When Browsers Download Images Identifying, Auditing, and Discussing Third Parties My Digital Music Setup Measuring the Hard-to-Measure Finding Dead CSS The Fallacies of Distributed Computing (Applied to Front-End Performance) Ten Years Old Relative Requirements Airplanes and Ashtrays Performance and Resilience: Stress-Testing Third Parties Refactoring Tunnels Little Things I Like to Do with Git Writing Tidy Code Configuring Git and Vim Base64 Encoding & Performance, Part 2: Gathering Data Base64 Encoding & Performance, Part 1: What’s Up with Base64? Code Smells in CSS Revisited Typography for Developers Moving CSS Wizardry onto HTTPS and HTTP/2 Ack for CSS Developers A New Year, a New Focus Preparing Vim for Apple’s Touch Bar Choosing the Correct Average CSS Shorthand Syntax Considered an Anti-Pattern CSS Wizardry Newsletter Nesting Your BEM? Improving Perceived Performance with Multiple Background Images Continue Normalising Your CSS Pure CSS Content Filter Pragmatic, Practical, and Progressive Theming with Custom Properties Refactoring CSS: The Three I’s Speaker’s Checklist: Before and After Your Talk Improving Your CSS with Parker The Importance of !important: Forcing Immutability in CSS Mixins Better for Performance Managing Typography on Large Apps White October Events Workshop Partnership BEMIT: Taking the BEM Naming Convention a Step Further Travelling Like You Want to, When You Have To Contextual Styling: UI Components, Nesting, and Implementation Detail Subtleties with Self-Chained Classes Cyclomatic Complexity: Logic in CSS Immutable CSS Can CSS Be Too Modular? More Transparent UI Code with Namespaces When to use @extend; when to use a mixin The Specificity Graph CSS Wizardry Ltd.: Year 1 in review
Hacks for dealing with specificity
Harry Roberts · 2014-07-17 · via CSS Wizardry

Written by on CSS Wizardry.

Table of Contents

Independent writing is brought to you via my wonderful Supporters.

  1. Low specificity IDs
    1. Featured case study: NHS
  2. Safely increasing specificity

As we’re all probably well aware by now, specificity is one of the quickest ways to get yourself in a tangle when trying to scale a CSS project: even if you have the most considered source order, and your rulesets cascade and inherit to and from each other perfectly, an overly-specific selector can completely undo all of it. Specificity throws a real curve-ball at a language which is entirely dependent upon source order. To make things worse, you can’t opt out of it, and the only way to deal with it is by getting more and more specific.

On larger projects, this is something we can really do without.

Like I said, we can’t opt out of specificity, but there are a number of things we can do to mitigate its effects:

  • Never use IDs in CSS, ever. They have no advantage over classes (anything you can do with an ID, you can do with a class), they cannot be reused, and their specificity is way, way too high. Even an infinite number of chained classes will not trump the specificity of one ID.
  • Do not nest selectors unnecessarily. If .header-nav {} will work, never use .header .header-nav {}; to do so will literally double the specificity of the selector without any benefit.
  • Do not qualify selectors unless you have a compelling reason to do so. If .nav {} will work, do not use ul.nav {}; to do so would not only limit the places you can use the .nav class, but it also increases the specificity of the selector, again, with no real gain.
  • Make heavy use of classes because they are the ideal selector: low specificity (or rather, all classes have the same specificity, so you have a level playing field), great portability, and high reusability.

tl;dr never use a selector more specific than the one you need.

These are all very simple rules—and are very easy to follow if you’re starting a new project—but what happens when you need to hack specificity? We all know about !important, which I won’t go into here, but how can we trick specificity into being lowered or increased with no drastic side effects?

Low specificity IDs

Rules are the children of principles.

Jamie Mason

If you’ve ever been on any of my workshops, you will know that—right up front—I like to stress that no rules are unbreakable. There will always be exceptions, there will always be a situation which requires a rule to be bent, there will always be anomalies. Whenever someone says always do x, apply some critical thinking to work out the principles behind that rule, and take and break the bits you need to.

One exception to this exception, however, is the use of IDs. There is never a time when using an ID in CSS makes sense; there is never a good reason to use one; this rule is not breakable. Even if you were working with third-party markup that you can’t edit, and all that is in that markup is an ID, you can still avoid using that ID in your CSS.

Featured case study: NHS

How I helped the NHS rapidly build a brand new product.

Read case study…

N.B. Using IDs in your HTML, as fragment identifiers, or in your JS, as hooks, is totally fine—it’s in CSS that IDs are troublesome.

Let’s imagine you have this third-party widget embedded on your page, and you want to style it:

<div id="widget">
    ...
</div>

Naturally, given that we can’t edit this HTML to use a class instead of (or alongside) the ID, we’d opt for something like this:

Now we have an ID in our CSS, and that is not a good precedent to set. Instead, we should do something like this:

This is an attribute selector. This is not selecting on an ID per se, but on an element with an attribute of id which also has a certain value. This particular selector is basically saying Hey, find me an element with an attribute called id which has a value of widget.

The beauty of this selector is that it has the exact same specificity as a class, so we’re selecting a chunk of the DOM based on an ID, but never actually increasing our specificity beyond that of our classes that we’re making liberal use of elsewhere.

But this is a hack.

Just because we know a way of using IDs without introducing their heightened specificity, it does not mean we should go back to using IDs in our CSS; they still have the problem of not being reusable. Only use this technique when you have no other option, and you cannot replace an ID in some markup with a class.

Safely increasing specificity

I was recently reminded of this little trick after seeing it in Mathias Bynens’ slidedeck 3.14 Things I Didn’t Know About CSS: you can chain a selector with itself to increase its specificity.

That is to say:

…will select based on only one class (.btn) but with double the specificity. We can take this as far as we need to:

…but hopefully we’ll never get that far.

Let me illustrate this with an example: jsfiddle.net/csswizardry/3N53n.

Here we can see that the .box a {} (line 17) selector’s color declaration (line 18) overrides the .btn {} (line 22) selector’s color declaration (line 26), causing the button to use a totally unsuitable color which is the same as its background.

We could fix this with an !important (line 26): jsfiddle.net/csswizardry/3N53n/1, but ewww, no thanks.

We could also add another selector to the .btn {} ruleset (line 23): jsfiddle.net/csswizardry/3N53n/2, but this isn’t a very maintainable solution at all: what happens when it’s not just boxes that are the problem? We can’t really keep on adding a new selector every time we need to bump up specificity.

But what we could do is double the specificity of .btn {} against itself (line 28): jsfiddle.net/csswizardry/3N53n/3

This still isn’t great, but it does heighten the specificity of the color declaration (and any other declarations we choose to place in the .btn.btn {} ruleset) without having to depend on a context (e.g. when in a .box, when in the .nav, etc.) and without having to keep a growing list of selectors maintained. This is a really nice way of increasing specificity in isolation.

Again, this is something of a hack, but it’s the best of a bad bunch when it comes to increasing specificity. At least this way there’s very little maintenance overhead, and no reliance on a location or context.

So there we have it; two ways of safely hacking (and remember, these are hacks) your specificity up or down.