htmlcsssasslesscss-specificity

CSS specificity based on proximity to element instead of order in css code


I have an ongoing issue where my css rules are jostling for control. Given this sass:

.green-theme {
    .theme-button {
        background: green;
    }
}

.blue-theme {
    .theme-button {
        background: blue;
    }
}

and this html:

<div class="blue-theme">
    <div class="green-theme">
        <button class="theme-button">should be green</button>
    </div>
</div>

My button is blue, because the blue-theme rule comes later in the css but I want it to be green as it is more closely nested to a .green-theme.

These themes are generated in sass so they are all the same. Is there a way I can flip this so it draws specificity from the proximity to the HTML element instead of order in the css file?


Solution

  • For this specific use case, CSS variables help a lot.

    .blue-theme {
      --btn-color: blue;
    }
    
    .green-theme {
      --btn-color: green;
    }
    
    .theme-button {
      background: var(--btn-color);
      color: white;
    }
    <div class="blue-theme">
        <div class="green-theme">
            <button class="theme-button">should be green</button>
        </div>
    </div>
    
    <div class="green-theme">
        <div class="blue-theme">
            <button class="theme-button">should be blue</button>
        </div>
    </div>

    That said, the disjoint between the CSS definition order and the HTML hierarchy sounds like a significant code smell, but it's hard to make a recommendation without knowing more context.