csscss-specificity

overriding class style with button:disabled pseudo-selector's style without important


I have a CSS stylesheet where I am styling a button element. What I am having trouble with is the button:disabled selector's style, which is going to be overridden by the additional classes applied to the element. Consider the following .primary class:

button { background-color: #F5F5F5; border-color: #F0F0F0; color: #000; }
button:hover { background-color: #FFF; }
button:active { background-color: #E5E5E5; }
button:disabled { background-color: transaprent; border-color: transparent; color: #777; }

button.primary { background-color: #9F03FF; border-color: #8400DA; color: #FFF; }
button.primary:hover { background-color: #AF2CFF; }
button.primary:active { background-color: #7800C1; }
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.2/css/bootstrap.min.css" rel="stylesheet"/>

<button disabled="disabled">Default disabled</button>

<!--
  the following will appear with the button.primary style
  and will react to :hover and :active state changes
  instead of showing the button:disabled style
-->
<button class="primary" disabled="disabled">Primary disabled</button>

In the design I'm trying to implement, all disabled buttons will always have the same style, that of the default disabled button, no matter which color styling class is applied.
I know I could apply the style again on a button.primary:disabled selector, but that would duplicate that style a lot (there are 6 color styling classes, with both light and dark variants, totaling 12 duplications).
I know I could also use !important just for the button:disabled style, and I would be fine with this - but I am looking for ways to avoid it, if possible.
Finally, I could use the :not(:disabled) selector on all color styling classes, but it produces quite ugly and not easily readable code.

How can I achieve my styling without duplicating the :disabled style, and without using !important?


Solution

  • This goes against how CSS cascades. What I would do is create a class called

     .if-disabled:disabled {
    ...... your styling here
    }
    

    And then

    <button class="primary if-disabled" />
    

    I might tweak it for readability, and if you are using any kind of library, there are a lot of ways to do this efficiently, but the trick is to create a more specific styling that you can put anywhere.