What Is the Rule Behind "CSS 256 Classes Override One Id"

What is the rule behind CSS 256 Classes Override One ID?

This happens due to a browser limitation, and not a mistake in the spec or how browsers implement it.

The spec says:

A selector's specificity is calculated as follows:

  • count the number of ID selectors in the selector (= a)
  • count the number of class selectors, attributes selectors, and pseudo-classes in the selector (= b)
  • count the number of type selectors and pseudo-elements in the selector (= c)
  • ignore the universal selector

Selectors inside the negation pseudo-class are counted like any other, but the negation itself does not count as a pseudo-class.

Concatenating the three numbers a-b-c (in a number system with a large base) gives the specificity.

Browsers have to store specificity values as integers for the purposes of calculation, and somehow a value of 256 causes an overflow depending on the browser. This usually happens with an 8-bit unsigned integer, whose max value is 255; adding one more causes the class-level specificity to somehow be "upgraded" into an ID-level value, making it equal to the ID in the cascade and thereby overriding it.

Why don't media queries override normal CSS?

In theory, no - you don't need the !important flag. The issue you are probably experiencing arrises from specificity:

Specificity is the means by which browsers decide which CSS property values are the most relevant to an element and, therefore, will be applied. Specificity is based on the matching rules which are composed of different sorts of CSS selectors

Mozzila

The basic math (hugely simplified) behind specificity is a weighted approach.

id is worth 100,
class is worth 10,
tag is worth 1.

Therefore a.class (tag + class = 11) is less specific that a#id (tag + id = 101).

CSS is also applied in a last-match-wins format, that is to say that the style for the last declared selector that matches will be applied (sorted according to the above specificity).

So - in your example, it could be that there are elements on you page with the class .element which is being targeted with a more specific selector (such as .container div > ul li + li .element (which is a lot more specific than just .element) so the styles from that is overriding the styles from your media style.

The caveat to this, is if the !important flag is being used. In which case the only way to override the styles is to supply the !important flag again.

How are the points in CSS specificity calculated

Pekka's answer is practically correct, and probably the best way to think about the issue.

However, as many have already pointed out, the W3C CSS recommendation states that "Concatenating the three numbers a-b-c (in a number system with a large base) gives the specificity." So the geek in me just had to figure out just how large this base is.

It turns out that the "very large base" employed (at least by the 4 most commonly-used browsers*) to implement this standard algorithm is 256 or 28.

What this means is that a style specified with 0 ids and 256 class-names will over-ride a style specified with just 1 id. I tested this out with some fiddles:

  • 255 classes are not enough to override 1 id

  • ...but 256 classes are enough to override 1 id

  • ...and 256 tag-names are enough to override 1 class-name

  • ...but, alas 256 ids are not enough to override 1 inline style (Updated 2012/8/15 -- you'll have to use !important)

So there is, effectively, a "point system," but it's not base 10. It's base 256. Here's how it works:

(28)2 or 65536, times the number of ids in the selector

  • (28)1 or 256, times the number of class-names in the selector
  • (28)0 or 1, times the number of tag-names in the selector

This isn't very practical for back-of-the-envelop exercises to communicate the concept.

That's probably why articles on the topic have been using base 10.

***** [Opera uses 216 (see karlcow’s comment). Some other selector engines use infinity — effectively no points system (see Simon Sapin’s comment).]

Update, July 2014:

As Blazemonger pointed out earlier in the year, webkit browsers (Chrome, Safari) now appear to use a higher base than 256. Perhaps 216, like Opera? IE and Firefox still use 256.

Update, March 2021:

Firefox no longer uses 256 as a base.

How to choose between `class` and `id`

Use id to identify elements that there will only be a single instance of on a page. For instance, if you have a single navigation bar that you are placing in a specific location, use id="navigation".

Use class to group elements that all behave a certain way. For instance, if you want your company name to appear in bold in body text, you might use <span class='company'>.

CSS class conflicting with CSS id

Remove the position:fixed from your .scrollableContainer in your css. It is what causing your table to float.

Here is a JSFiddle of your code: http://jsfiddle.net/wpkaJ/

Here it is after my suggestion: http://jsfiddle.net/wpkaJ/1/

Override span in html css and use TD

Edit: For a better explanation of the issue and solutions for different scenarios, please see Jukka's answer below.

Original Answer:

In CSS selectors, the one that is the closest to the actual element is applied. So you should be more specific when using selectors to override the style.

In your example the span element has an inline style which is of the highest specificity.

To gain higher specificity then inline style in an outer element you should use [style] and important.

You can force the one set on td like this:

td.set_font [style] {font-size:120px !important;}

Here is working JSFiddle

How do I make a class take precedence over an id?

What you have there is a CSS specificity problem.

.wider has a specificity of 0,0,1,0 while #normal has 0,1,0,0. You can't beat an ID with anything else than an ID (or inline definitions, but that is not the case here).

What I would recommend, if you cannot put the needed width declaration in the #normal selector, is to put it in #normal.wider or, if that either isn't possible, have an identified container, say #container, as high in the hierarchy as possible (maybe an ID on the body?) and replace .wider with #container .wider. This new selector will have a specificity of 0,1,1,0 which is a bit higher than 0,1,0,0.

Using !important will work too, but it should be used only as a last resort.

Example:

<div id="container" class="wrapper">
<div id="normal" class="wider">
</div>

For this HTML snippet some possible selectors in decreasing order of specificity would be:

CSS Selector         -> Specificity
---------------------------------------
#container #normal -> 0,2,0,0
#container .wider -> 0,1,1,0 // These two have the same specificity so
#normal.wider -> 0,1,1,0 // the last declared value will be used
#normal -> 0,1,0,0
.wrapper .wider -> 0,0,2,0
.wider -> 0,0,1,0

How to apply !important using .css()?

Most of these answers are now outdated, IE7 support is not an issue.

The best way to do this that supports IE11+ and all modern browsers is:

const $elem = $("#elem");
$elem[0].style.setProperty('width', '100px', 'important');

Or if you want, you can create a small jQuery plugin that does this.
This plugin closely matches jQuery's own css() method in the parameters it supports:

/**
* Sets a CSS style on the selected element(s) with !important priority.
* This supports camelCased CSS style property names and calling with an object
* like the jQuery `css()` method.
* Unlike jQuery's css() this does NOT work as a getter.
*
* @param {string|Object<string, string>} name
* @param {string|undefined} value
*/
jQuery.fn.cssImportant = function(name, value) {
const $this = this;
const applyStyles = (n, v) => {
// Convert style name from camelCase to dashed-case.
const dashedName = n.replace(/(.)([A-Z])(.)/g, (str, m1, upper, m2) => {
return m1 + "-" + upper.toLowerCase() + m2;
});
// Loop over each element in the selector and set the styles.
$this.each(function(){
this.style.setProperty(dashedName, v, 'important');
});
};
// If called with the first parameter that is an object,
// Loop over the entries in the object and apply those styles.
if(jQuery.isPlainObject(name)){
for(const [n, v] of Object.entries(name)){
applyStyles(n, v);
}
} else {
// Otherwise called with style name and value.
applyStyles(name, value);
}
// This is required for making jQuery plugin calls chainable.
return $this;
};
// Call the new plugin:
$('#elem').cssImportant('height', '100px');

// Call with an object and camelCased style names:
$('#another').cssImportant({backgroundColor: 'salmon', display: 'block'});

// Call on multiple items:
$('.item, #foo, #bar').cssImportant('color', 'red');

Example jsfiddle here.



Related Topics



Leave a reply



Submit