HTML Structure: Building the Foundation Right
Learn semantic HTML elements and proper document structure. We’ll walk through the markup that makes CSS easier and helps search engines understand your content.
Read ArticleUnderstanding selectors is crucial. We’ll cover classes, IDs, pseudo-classes, and why specificity matters when your styles aren’t applying the way you expect.
If you’ve ever written a CSS rule and wondered why it didn’t work, you’ve met the specificity problem. It’s one of those things that seems simple at first — just target an element and style it, right? But CSS selectors are more nuanced than that.
The browser has to decide which styles actually apply when you’ve got multiple rules targeting the same element. That’s where specificity comes in. It’s not magic, and it’s not broken — it’s just a system with rules. Once you understand how it works, you’ll stop fighting against CSS and start writing styles that actually stick.
We’re going to walk through the most common selectors you’ll use, show you how specificity gets calculated, and give you practical strategies for keeping your stylesheets organized and predictable.
CSS gives you several ways to target elements. Each type has its own specificity weight, and understanding these weights is the key to controlling which styles win.
Target all instances of an HTML tag. Super simple, very low
specificity.
p { color: blue; }
hits every paragraph on the page.
Target elements with a specific class. Much more specific
than element selectors. You can reuse classes across
multiple elements — that’s the whole point.
.button { padding: 1rem; }
Target a single element with a unique ID. These have very
high specificity, which can create problems if you’re not
careful.
#header { background: white; }
— and there should only be one element with that ID.
Target elements based on their attributes.
input[type="email"]
targets only email inputs. Same specificity as a class
selector.
Target elements in a specific state or position.
a:hover
,
li:first-child
,
input:focus
— same specificity as a class.
Specificity is calculated as a four-part score. Don’t let that intimidate you — it’s straightforward once you see it.
The four parts are: inline styles, IDs, classes and pseudo-classes, and elements . When you write a selector, you count how many of each type you’re using. A selector with more IDs will always beat one with just classes. A selector with classes will beat one with just elements.
Here’s the thing though — you’ll rarely need to think about specificity in numbers. Just remember this: avoid using IDs for styling (they’re too specific), stick with classes, and you’ll stay out of trouble. If a style isn’t applying, the problem is almost always that a more specific selector is overriding it.
“The best CSS is the CSS you don’t have to override. Write specific enough to target what you need, but not so specific that you paint yourself into a corner.”
Once you’re comfortable with basic selectors, you can combine them to target elements more precisely. Combinators let you say things like “paragraphs inside a div with the class article” or “links that come right after a heading.”
The descendant combinator (space) is the most common:
.article p
targets all paragraphs inside anything with class article. The
child combinator (
>
) is more specific — it only targets direct children.
.article > p
means paragraphs that are immediate children of an element with
class article, not nested deeper.
There’s also the adjacent sibling combinator (
+
) which targets the next element in the flow, and the general
sibling combinator (
~
) for any sibling that follows. These are powerful for styling
things like the first paragraph after a heading differently than
the rest.
Use classes instead of IDs. Avoid nesting selectors too deeply. The simpler your selector, the easier it is to override when you need to. A single class is almost always better than a long chain of selectors.
Name your classes for what they do, not what they look like.
Don’t use
.red-text
— use
.warning-message
. When the design changes, your HTML stays accurate and your
CSS is still clear.
Just don’t. If you’re reaching for !important, it’s usually a sign that your specificity is out of control. Fix the root cause instead. You’ll thank yourself later when you’re trying to debug why a style won’t change.
Pick a naming convention and stick with it. BEM (Block Element Modifier) works great for keeping your classes organized and predictable. Whatever you choose, consistency makes your stylesheets way easier to maintain over time.
Open DevTools, inspect elements, and verify that your selectors are targeting what you expect. You can see the specificity calculation there too. It’s the fastest way to debug style issues.
Define reusable values in your CSS variables. It’s not about selectors per se, but it keeps your stylesheets maintainable and makes global changes a breeze. Colors, spacing, fonts — put them in variables.
CSS selectors and specificity aren’t complicated once you understand the core concepts. You don’t need to memorize specificity scores — just remember that IDs are high-specificity, classes are medium, and elements are low. Prefer classes, avoid IDs for styling, and keep your selectors simple.
The real skill is writing selectors that are specific enough to target what you need but flexible enough that you can maintain your code months or years later. That comes from practice and from learning to use DevTools to see what’s actually happening in your browser.
Once you’ve got selectors down, you’re ready to tackle more advanced CSS — layouts, animations, responsive design. Everything builds on this foundation.
This article provides educational information about CSS selectors and specificity. Browser behavior, CSS specifications, and best practices can evolve over time. While we’ve aimed for accuracy, web technologies update frequently. For the most current CSS specifications and browser compatibility information, refer to W3C CSS specifications or MDN Web Docs . Your specific project requirements, browser support needs, and design system may require different approaches than those discussed here.