CSS For Designers

CSS Specificity – Preview

We know from our introduction to the cascade that when more than one rule targets a selector, CSS merges the rules. We also know that if the same property is declared twice, the last rule to be loaded is the one that will be used.

p {
    font-size: 1rem;
    color: #000;
}
p {
    font-size: 2rem;
}

In this example, the p would have a font size of 2rem and appear black (#000). What about if we introduced a class to this example?

.anything {
    font-size: 1rem;
}
p {
    font-size: 2rem;
}

If we had the following HTML code, what size would the text be?

<p class="anything">What size will this text be?</p>

The answer is 1rem because the class (anything) has a higher specificity than p.

Class?

A class is a type of selector. You may already be familiar with these but, if not, we’ll be looking at them later in the course.

Why does this matter?

Anyone who applies CSS to WordPress, Squarespace or any other CMS template, is probably familiar with using the inspector to find the selector you need to target.

A classic example would be a navigation bar. You might see some HTML that looks like this:

<nav class="main-nav">
    <ul class="menu">
        <li class="menu-item"><a href="#">Item One</li>
        <li class="menu-item"><a href="#">Item Two</li>
        <li class="menu-item"><a href="#">Item Three</li>
    </ul>
</nav>

You could reasonably expect to be able to target the links with the following CSS:

.main-nav a {
    color: #000;
}

Only to find that that doesn’t work because the theme author has written the following CSS:

.main-nav .menu li.menu-item > a {
    color: blue;
}

Their CSS will take priority because it has a higher specificity than yours. In many of these situations, the minimum CSS you can write to override their styles is to copy the selector they’ve used.

In this case, that would be: .main-nav .menu li.menu-item > a.

.main-nav .menu li.menu-item > a?!

Don’t worry about what all of this means: we’ll cover it later!

Keep specificity low

Ideally, you want to keep your CSS specificity as low as possible...but no lower! Some CSS methodologies and frameworks keep CSS extremely low.

When writing CSS, try to limit the number of selectors you use wherever possible.

How specificity is calculated

Different types of selector have different levels of specificity. From least to most specific, they’re ranked as follows:

  1. Universal selector (*)
  2. Type/tag/element selectors (p) and pseudo-elements (::after)
  3. Classes (.class-name), attributes ([input="submit"]) and pseudo-classes (:hover)
  4. ID selectors (#id-name)
  5. Inline styles (style="" written in the HTML)
  6. !important

CSS categorises numbers 2–5 and into different weights, then counts how many of each selector type is used. Numbers 1 and 6 and excluded from the calculation because:

  • The universal selector (*) has no bearing on specificity
  • !important will override any other combination

Because you’re going to keep specificity low in your CSS, we’re not going to go into the calculation here. But if you want to see how it’s worked how, here are some great visual guides:

Why you shouldn’t use !important

The use of !important is frowned upon because there are few reasons to use it. Three genuine cases might be:

  • Needing to override a style declared in the HTML (e.g. <p style="font-size: 1em;">)
  • To override the use of !important in a stylesheet you can’t change
  • As a super quick fix when you don’t have time to get to the bottom of a CSS specificity issue

Outside of these circumstances, it shouldn’t be used because:

  • The only way to override it is by using another !important
  • You can achieve what you need by increasing the specificity of your code

Avoid them except where absolutely necessary.

What about media queries?

Media queries have no bearing on specificity but, as with all CSS, their written order is important.

p {
    font-size: 1rem;
}
@media (min-width: 768px) {
    p {
        font-size: 1.25rem;
    }
}

In this example, the p font size would increase to 1.25rem as soon as the browser was at least 768px wide. If we reversed the order of rules, the font size would be 1rem at all browser widths.

For that reason, media queries are generally written at the end of a stylesheet or section of a stylesheet.

Media queries?

Media queries are what we use to apply CSS rules at specific viewport widths. If we wanted a paragraph to have blue text on smaller screen sizes and red text on screens at least 1000px wide, we could write:

p {
    color: blue;
}
@media (min-width: 1000px) {
  p {
    color: red;
  }
}

Found this useful?

Early access to the course is available now at an introductory price of $169 (instead of $195) + EU Digital VAT.

$169 – Buy Now