How to Deal with Issues in CSS Specificity

Cascading Style Sheets

No matter whether you're working on a small or a large-sized web design and development project, you can't overlook the coding part, since it can help adjust your solution according to your specifications.

However, writing code can be a challenging task since even a little typographical error can have a huge negative impact on your end-product. Besides, a lot of other issues crop up during the coding phase that you will need to resolve, especially when working with Cascading Style Sheets. For instance, CSS Specificity is an issue that more likely concerns developers working on bigger projects.

If you want to reduce the time that is spent on finding bugs, it is important for you to understand how your code is interpreted by the browsers. And for that, you require a good understanding of CSS Specificity and how it works. In this post, I'll be helping you explore CSS Specificity and how you can handle the issues associated with it using Preprocessors.

Understanding CSS Specificity and Its Issue

Specificity in Cascading Style Sheets is basically a process that helps decide about the CSS rules that need to be applied by web browsers. In fact, CSS Specificity is the main reason because of which cascading style sheet (CSS) rules can't be applied to certain elements. Moreover, it helps in deciding which rule will have priority over other CSS rules.

If you want an easy way to handle the selector specificity issue, then a viable option is to use the BEM or Block Element Modifier method. BEM is a brilliant front-end toolkit that organizes the structure of cascading style sheet (CSS) and make it easy to understand. This method refrains users from having to reflect a block that comes prepackaged with nested DOM structure. And, the best thing about the BEM method is that the specificity does not change for every selector. Thus, you won't have to worry about issues caused due to overly specific selectors.

In order to keep specificity low, the BEM methodology allows to write classes and not IDs in an HTML document. Now, since you will only have to use classes for your CSS, the specificity of each and every CSS selector will be 0,1,0.

While BEM is an effective technique to handle specificity issues for front-end developers who are involved mainly with HTML based projects, it does not prove a great option for developers who develop content management systems. After all, CMS code editors do not need HTML coding knowledge for laying out the content structure. This is why, you cannot use BEM for all your projects. A viable alternative is to make use of CSS Preprocessors like SASS, LESS and a few others.

How You Can Deal With CSS Specificity

As discussed above, you can deal with the CSS Specificity issues with the help of CSS Preprocessors. Here. I'll be talking about two approaches that use CSS Preprocessors to resolve the specificity problem:

  1. Prepend the Existing Selector

    Whenever you face a specificity problem and are forced to make a selector heavier compared to another, then it is recommended that you should prepend your already existing selector with a new class, id, type selectors, etc. You can either prepend the reference selector & used in your cascading style Sheets or else use CSS to accomplish the task, using the following code snippet:

    .yellow{
        .btn & {
            color: yellow;
        }
    }

    This will produce the following output:

    .btn .yellow {
        color: yellow;
    }

    Probably, you might wish to prepend the selector with the help of an html or a body tag. However, a better option is to use something more specific available on your pages like the #wrapper, .page, etc. Also, you can make your selector ready to adapt to any changes that will take place in the future. For this purpose, you can make use of Sass that helps add the prepending selector in a variable as follows:

    $PrependVar1: "header &";
    $PrependVar2: "footer &";
    
    .block {
        #{$PrependVar1} {
            width: 55%;
        }
        #{$PrependVar1} {
            width: 37%;
        }
    }
    

    The above code will produce the following output:

    header .block {
        width: 55%;
    }
    
    footer .block {
        width: 37%;
    }
  2. Use a Self-chained Selector

    Undoubtedly, prepending a selector proves a useful approach, but isn't a good scalable solution. A better alternative is to make use of CSS’s feature that increases the specificity using self-chained selectors.

    The self-chained selectors also work well with ids, classes, etc. except for type selectors. When using classes for styling your CSS, using a self-chained selector provides a scalable way to override any specific selector.

    Thanks to the parent reference selector, you can chain the same selector to itself many different times, as you can see in the code below:

    .classSelector {
        &#{&} {
           width: 55%;
        }
        &#{&}#{&} {
            width: 37%;
        }
    }
    
    .classSelector.classSelector {
        width: 55%;
    }
    
    .classSelector.classSelector.classSelector {
        width: 55%;
    }

    In case, you find the above code confusing, you can create a mixin to increase the specificity along with Sass 3.4, as follows:

    @mixin block($number: 1) {
        $selector: &;
    
        @if $number > 1 {
            @for $i from 1 to $number {
                $selector: $selector + &;
            }
    
            @at-root #{$selector} {
                @content;
            }
        }
        @else {
            @content;
        }
    }
    
    .selector {
        @include block(2) {
            width: 55%;
        }
    
        @include block(3) {
            width: 37%;
        }
    }

    The resulting CSS will look something like:

    .selector. selector {
        width: 55%;
    }
    
    .selector.selector.selector {
        width: 37%;
    }

You can also use LESS and Stylus CSS Pre Processors for self-chaining.

Self-chaining will help in increasing the specificity of any selector and will help in making it infinitely scalable.

Final Thought

The CSS Preprocessors are getting evolved, however, developers still don't pay much attention to using them in the correct way. The biggest benefit of CSS Preprocessors is that they can help you tackle with specificity problems that you might encounter when working on your style sheets.

Resources