CSS Specificity and its Application!

CSS Specificity and its Application!

CSS specificity is a crucial concept that determines which styles are applied to elements when multiple conflicting rules exist. Understanding specificity is essential for maintaining control over the appearance of web content and ensuring consistent design across a website.

In this guide, we'll explore CSS specificity in-depth, discussing what CSS specificity is, its importance, how to understand its calculation, specificity hierarchy, CSS selectors and other important headings that will be discussed as well.

Before moving further to what specificity is all about, a quick explanation to what CSS means will be of help to people who know little or nothing about CSS.

Cascading Style Sheets (CSS) is a style sheet language used to describe the presentation of a document written in a markup language such as HTML. CSS is a powerful tool that can be used to control the appearance of a document, including the font, color, size, and layout of text, images, and other elements.

CSS is used to style the web pages. It can be used to change the font, color, size, and layout of text, images, and other elements. CSS can also be used to create animations and other effects.

What is CSS Specificity?

CSS specificity is the set of rules applied to CSS selectors in other to determine which style is applied to the element. If an element has two or more selectors with conflicting style rules, a browser will look at the specificity score to determine which style should be applied. Those property values with more relevance to the element will have a higher specificity value.

Most cases, developers tend to make mistakes as they target an HTML element more than once, in this case, specificity helps to determine which of the selector's style rules will be applied.

Importance of CSS Specificity to web developers

Specificity is important because it allows developers to control the styling of their web pages precisely. Without it, the browser would have no way of determining which rule should take precedence, potentially leading to unexpected or inconsistent visual results.

Specificity is important because it allows you to control the order in which CSS rules are applied. This can be useful for overriding default styles or creating more complex layouts.

In collaborative projects, consistent understanding and application of specificity ensure that team members can work seamlessly on the same code base without inadvertently causing styling conflicts.

Understanding Specificity Calculation

The specificity calculator tells you the weight of a CSS selector to determine which rule from competing CSS declarations gets applied to an element.

How is Specificity Calculated?

The weight is determined by the number of selectors of each weight category in the selector matching the element (or pseudo-element). The specificity algorithm is basically a three-column value of three categories or weights - ID, CLASS, and TYPE - corresponding to the three types of selectors. Start at 0, add 100 for each ID value, add 10 for each class value (or pseudo-class or attribute selector), add 1 for each element selector or pseudo-element.

Specificity Hierarchy

Every selector has it's own specificity, and if two selectors apply to the same element, the one with the higher specificity wins. All css selectors has it's place in the specificity hierarchy. There are four distinct categories which define the specificity level of a given selector. We will start with the selector type with the highest specificity down to the selector type with the lowest specificity.

CSS Selectors

Simple Selectors

  • CSS ID Selectors: The CSS ID selects an HTML element based on the value of it's ID attribute.
#my_id {
    property: value;
}
  • CSS Class Selectors: The CSS class selector matches and selects HTML elements based on the value of the given class. Specifically, it selects every single element in the document with that specific class name.
.my_class {
    property: value;
}
  • CCS Type Selectors: The CSS type selector selects all HTML elements of the specified type.
p {
    property: value;
}
  • CSS Universal Selectors: The CSS universal selector selects everything. It selects every single element in the document.
* {
    property: value;
}

Attribute Selectors

The CSS attribute selectors matches and selects HTML elements based on the presence of an attribute or a specific attribute value. One of the most popular HTML attributes you may have come across is the href attribute, which is added to the opening < a > tag and specifies the URL the < a > links to.

<a href="https://www.freecodecamp.org/">The best place to learn to code for free!</a>

Grouping Selectors

The CSS grouping selector helps you to target and style more than one element at once. To use the grouping selector, use a comma to group and separate the different elements you want to select.

div, p, span {
    property: value;
}

The code above matches div, p, span elements on the page and those three elements will share the same styling.

CSS Combinators

Combinators allow you to combine two elements based on the relationship between the elements and there location in the document. The four types of combinators are;

  • The Descendant Combinators: As the name implies, the descendant combinators selects only the descendants of the specific element. We first mention the parent element, leave a space, and then mention the descendant of the first element, which is the child element of the parent. The child element is an element inside the parent element.
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="main.css">
  <title>Document</title>
</head>
<body>
  <div>
    <h2>I am level 2 heading</h2>
    <p>I am a paragraph inside a div</p>
    <span>I am a span</span>
    <p>I am a paragraph inside a div</p>
  </div>
  <p>I am a paragraph outside a div</p>
</body>
</html>

In the example above, the div is the parent, h2, span, and two p's are the child elements because they are inside the div. There is also a paragraph outside the div.

If you want to style only the paragraphs that are inside the div, here is what you should do:

div p {
    property: style;
}
  • The Direct Child Combinator: The direct child combinator, also known as the direct descendant, selects only the direct children of the parent.

To use the direct child combinator, specify the parent element, then add the > character followed by the direct children of the parent element you want to select.

Let's take the following as an example:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="main.css">
  <title>Document</title>
</head>
<body>
  <div>
    <a href="#">I am a link</a>
    <a href="#">I am a link</a>
    <p><a href="#">I am a link inside a paragraph</a></p>
  </div>
</body>
</html>

There is a div which is the parent element.

Inside the parent element, there are two a elements which are the direct children of the div.

There is also another a element inside a p element. The p element is a child of the div, but the a element inside the paragraph is not a direct child of the div.

So, to access only the a elements that are direct children of div, you would do the following:

div > a  {
    property: value;
}

The code above matches the a elements directly nested inside the div element and are immediate children.

  • The General Sibling Combinators: The general sibling combinator selects siblings.

You can specify the first element and a second one that comes after the first one. The second element doesn't need to come right after the first one.

To use the general sibling combinator, specify the first element, then use the ~ character followed by the second element that needs to follow the first one.

Let's take the following as an example:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="main.css">
  <title>Document</title>
</head>
<body>
  <div>
    <p>I am paragraph inside a div</p>
  </div>
  <p>I am a paragraph outside a div</p>
  <h3>I am a level three heading</h3>
  <p>I am a paragraph outside a div</p>
</body>
</html>

The div has a p element nested inside it. That specific p element is a child of div.

There are also two paragraphs with the text 'I am a paragraph' outside a div and an h3 element. All those three elements are siblings of the div element.

So, to select the p elements that are siblings of the div element, you would do the following:

div ~ p {
    property: value;
}
  • The Adjacent Sibling Combinators: The adjacent sibling combinator is more specific than the general sibling combinator.

This selector matches only the immediate siblings. Immediate siblings are the siblings that come right after the first element.

To use the adjacent sibling combinator, specify the first element, then add the + character followed by the element you want to select that immediately follows the first element.

Let's revisit the example from the previous section:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="main.css">
  <title>Document</title>
</head>
<body>
  <div>
    <p>I am paragraph inside a div</p>
  </div>
  <p>I am a paragraph outside a div</p>
  <h3>I am a level three heading</h3>
  <p>I am a paragraph outside a div</p>
</body>
</html>

Although the p element that follows the h3 element is a sibling of the div element, it is not a direct sibling like the p element that comes before the h3.

So, to target only the p element that comes directly after the div, you would do the following:

div + p {
    property: value;
}

Pseudo-class Selectors

Pseudo-class selectors select elements that are in a specific state.

Some examples of the state the element can be in are:

  • The element is being hovered over by the mouse pointer.

  • The element is the first of its type.

  • The link has been visited before from that specific browser.

  • The link has not been visited before from that specific browser.

  • The checkbox/radio button has been checked.

  • Pseudo-class selectors start with a colon,:, followed by a keyword that reflects the state of the specified element.

The general syntax looks something like the following:

element:pseudo-class-name {
    property: value;
}

Pseudo-element Selectors

Pseudo-element selectors are used for styling a specific part of an element - you can use them to insert new content or change the look of a specific section of the content.

For example, you can use a pseudo-element to style the first letter or the first line of an element differently. You can also use pseudo-elements to add new content before or after the selected element.

In contrast to pseudo-classes that are preceded by a : character, pseudo-elements are preceded by a :: character.

The :: character is followed by a keyword that allows you to style a specific part of the selected element.

The general syntax looks something like the following:

element::pseudo-element-selector {
    property:value;
}

Inline Styles and Important Declaration

Inline Styles

Inline styles are a way to apply styling directly to an HTML element within the same line of code. They are defined using the "style" attribute within the opening tag of the element. Inline styles override any styles defined in external style sheets or inherited from parent elements because it has a specificity score of 1000.

!important Declaration

The "!important" declaration is used to override any conflicting styles applied to an element. When added to a style rule, it ensures that the specified style takes precedence over all other styles, regardless of their source.

Usage and Significance

Inline styles and the "!important" declaration are powerful tools that can be used to achieve specific styling effects or troubleshoot layout issues. However, they should be used sparingly and with caution.

Advantages
  • Inline styles provide a quick and easy way to apply unique styles to specific elements without modifying external style sheets.

  • The "!important" declaration can be useful for overriding unwanted styles or ensuring that a particular style is applied consistently across different browsers.

Disadvantages
  • Inline styles can make code cluttered and difficult to maintain, especially when used excessively.

  • The "!important" declaration can lead to style conflicts and make it challenging to manage and update styles in the future.

CSS Location and Cascade Layers

CSS Location refers to the position of a style rule in a CSS document. The location of a style rule determines its precedence and how it will be applied to elements on a web page. Style rules can be located in various places, including:

External Style Sheets

These are separate CSS files that are linked to an HTML document. External style sheets are typically used when the same styles need to be applied to multiple pages on a website.

Internal Style Sheets

These are style rules that are embedded within the head section of an HTML document. Internal style sheets are useful for applying unique styles to a single page.

Inline Styles

These are style rules that are applied directly to an HTML element using the style attribute. Inline styles are typically used for applying unique styles to a specific element.

CSS Cascade Order refers to the order in which CSS rules are applied to elements on a web page. The cascade order is determined by several factors, including:

  1. Specificity: The specificity of a CSS rule is determined by the number and type of selectors used in the rule. The more specific a rule is, the higher its priority in the cascade order.

  2. Source Order: The source order refers to the order in which style rules are listed in a CSS document. Rules that appear later in the document have a higher priority than rules that appear earlier.

  3. Inheritance: Some CSS properties can be inherited from parent elements to child elements. Inherited properties are applied to child elements unless they are overridden by a more specific rule.

Scoping Proximity

"Scoping proximity CSS" is a concept in Cascading Style Sheets (CSS) that allows you to apply styles to elements based on their position relative to other elements. It's a powerful tool for creating complex layouts and designs without having to write a lot of code.

Scoping proximity CSS can be used to create a variety of effects, such as:

  • Creating drop-down menus

  • Styling table rows and columns

  • Creating complex layouts with multiple columns

Best Practices in CSS

Best practices in CSS refer to guidelines and techniques that help developers write efficient, maintainable, and cross-browser compatible CSS code. These practices include:

  • Using a CSS reset: A CSS reset is a set of styles that normalize the default styles of different browsers, ensuring a consistent starting point for all elements.

  • Organizing CSS logically: This involves grouping related CSS rules together, using descriptive class names and IDs, and maintaining a consistent coding style.

  • Using semantic markup: Semantic markup means using HTML elements that accurately describe their content, which makes it easier for both humans and machines to understand the structure of the page.

  • Optimizing CSS performance: This includes techniques such as minifying CSS code, using CSS sprites, and leveraging browser caching.

Avoiding !important in CSS

Avoiding !important in CSS refers to the practice of not using the !important declaration in CSS. The !important declaration forces a style rule to take precedence over all other rules, which can make it difficult to maintain and override styles in the future. It is generally recommended to avoid using !important unless absolutely necessary.

Conclusion

When talking about Cascading Style Sheets (CSS),specificity holds the key to determining which style declarations triumph or take precedence when an element is targeted by multiple rules. It serves as a ranking system, ensuring styles cascade predictably and preventing unintended conflicts.

References

Here are some articles and sources where you can learn more about CSS Specificity:

  1. MDN Web Docs - CSS Specificity: https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity

  2. Frontend Masters - CSS Specificity: https://frontendmasters.com/blog/css-specificity/

  3. MDN Web Docs - CSS Cascade and Inheritance: https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance

  4. Smashing Magazine - CSS Specificity and Inheritance: https://www.smashingmagazine.com/2010/04/css-specificity-and-inheritance/

  5. CSS-Tricks - CSS Specificity: https://css-tricks.com/specifics-on-css-specificity/

  6. CSS Wizardry - Understanding CSS Specificity: https://csswizardry.com/2014/07/understanding-css-specificity/

  7. FreeCodeCamp - CSS Specificity: https://www.freecodecamp.org/news/css-specificity-explained-by-building-a-css-specificity-calculator-5a7738d24d2a/

  8. SitePoint - CSS Specificity: A Look Under the Hood: https://www.sitepoint.com/web-foundations/css-specificity-under-the-hood/

  9. W3Schools - CSS Specificity: https://www.w3schools.com/css/css_specificity.asp

  10. CSS Specificity Calculator: https://specificity.keegan.st/

These resources cover various aspects of CSS Specificity, including how to calculate specificity, best practices, and common pitfalls to avoid.