velis velis - 6 months ago 12
CSS Question

CSS style precedence not working as expected

I have two styles, each declared in its separate 3rd party control that don't play well together and I'm not even sure why that is - and ultimately - how to make them work as I want.

HTML:

<table>
<tr class="myrow">
<td>normal cell</td>
<td class="ui-state-error">error cell</td>
</tr>
</table>


CSS:

.myrow>td { /* declared in the grid component */
background-color: #88f;
}
.ui-state-error { /* declared in jQuery UI */
background-color: #f00;
}


Both HTML & CSS simplified to show the exact error. Here's the fiddle.

The end result here is both cells displaying blue background (FF 46.0).

However, I would expect the
.ui-state-error
to be more specific as it's applied directly to the cell in question vs. the
.myrow>td
rule which seems more general at first glance.

Regardless, the browser decides to apply
.myrow>td
CSS and I want to make it apply the
.ui-state-error
.

How can I do that considering the fact that CSS styles themselves are not under my control?

Answer

Both your rules are applied directly to the cell - one is via the class and other is via the element type. Since the selector with element type has another class selector attached to it, it has more specificity and hence wins.

The specificity of .ui-state-error selector is 010 because it has only one class selector as part of the complex selector whereas the .myrow > td selector's specificity is 011 as it has one class and one element type selector as part of the complex selector.

You can change the selector like given below to make the error td have red background.

.myrow > .ui-state-error {
  background-color: #f00;
}

Changing the selector like above will not override all other styles. It will override only selectors that are lower in specificity than 010 and apply only for element which have class='ui-state-error when their ancestor has class='myrow'.

If the myrow is a theme specific class and you want the .ui-state-error elements to be red in color irrespective of the theme then you could change the selector like below:

tr > .ui-state-error {
  background-color: #f00;
}

This also has specificity of 011 and would override the .myrow > td.


There is a specificity calculator available at https://specificity.keegan.st/ which you'd find very handy and useful till such time you get completely familiar with the specificity calculations.

To put it simple terms, below is how specificity is calculated:

  • Calculate the total number of id selectors that are part of the full selector. Take this as a
  • Calculate the total number of class, attribute and pseudo-class selectors that are part of the full selector. Take this as b.
  • Calculate the total number of element type and pseudo-element selectors that are part of the full selector. Take this as c.

The final specificity is a + b + c (concatenation and not sum).