Fuzzy Specificity Hack

Affects all versions of Internet Explorer and Opera prior to version 8

All versions of IE? Yep. IE8b1 is the latest in a long line of givers of love to the fuzzy. Anything about IE7 on this page is currently true of IE8b1.

  1. Basic fuzzy specificity hack
  2. Hacking for Opera 7.54 and below plus IE7
  3. Hacking for Opera 7.54 and below
  4. Hacking for Opera 8 and up
  5. Hacking for Opera 8 alone
  6. Hacking for IE7

Basic fuzzy specificity hack

A. <div class="fuzzy-hook-class"><div> ... </div></div>
This div shows red in Opera 7.54 and under and all versions of IE (including IE7) but shows blue in all other browsers.
.fuzzy-hook-class div { background: #ff0000; }
div.fuzzy-hook-class * { background: #0000ff; }

Let's get to the, er, specifics

Taking our cue from the W3's official position on specificity, we can see that the two rules

.fuzzy-hook-class = a-0 b-1 c-0, div = a-0 b-0 c-1 => specificity = a-0 b-1 c-1

div.fuzzy-hook-class = a-0 b-1 c-1, * = a-0 b-0 c-0 => specificity = a-0 b-1 c-1

have exactly the same specificity.

According to the specs, the latter rule should take precedence over the former. Indeed, if you switch the rules around the div shows red in "modern" browsers.

However, Opera (prior to 8) and all versions of Internet Explorer (PC and Mac) do things a little different. They seem to distinguish between elements with the same specificity, giving some kind of additional fuzzy weighting depending on the last part of the rule, eg tag beats id without tag beats class without tag beats universal selector.

So the method pans out like this:

[Is this a known way to hack IE? Surely I just can't mix the right googlejuice to summon it up. Whatever, it's way more complex and subtle than pre-existing IE hacks so it's just a potentially useful side-effect rather than a serious replacement]

NB. This bug still affects IE7.

Hacking just for Opera 7.54 and below (er, and IE7)

Anyhow, if we only want to feed rules to old versions of Opera and exclude IE, then we need to tweak the rules a little more. Fortunately that's pretty trivial...

B. <div id="op7-hook-id"><div class="target-class"> ... </div></div>
This div shows red in Opera 7.54 and under but shows blue in all other browsers (except IE7).
#op7-hook-id > div.target-class { /*\*/ background: #ff0000; /**/ }
div#op7-hook-id *.target-class { background: #0000ff; }

Alternatively, if there are no suitable hooks in the html to hang the Child Selector off that IE (PC) can't see, we could simply redeclare the rule and hide it with the Star HTML Selector hack.

In either case, IE5 (Mac) will need extra treatment - here, the perennial favourite, the Escaped Comment End hack.

Hacking just for Opera 7.54 and below (again)

Well, it was trivial to exlude IE, but the beta version of IE7 has changed all that. When IE7 actually comes out this may all change, but for now all we need to do (snore) is add an extra declaration with a CSS3 selector that IE7 can understand.

B1. <div id="op7A-hook-id"><div class="target-class"> ... </div></div>
This div shows red in Opera 7.54 and under but shows blue in all other browsers.
#op7A-hook-id > div.target-class { /*\*/ background: #ff0000; /**/ }
div#op7A-hook-id *.target-class { background: #0000ff; }
#op7A-hook-id[id^="op7A-hook-id"] > div.target-class { background: #0000ff; }

Hacking just for Opera 8 and up

Moving on, applying the same kind of trick inside a media query block, yields a hack that targets Opera 8 and above.

C. <div id="op8andup-hook-id"> ... </div>
This div shows red in Opera 8 and 9 but shows blue in all other browsers.
div#op8andup-hook-id { background: #0000ff; }
@media all and (min-width: 0px)
	{
	body #op8andup-hook-id { background: #ff0000; }
	}

NB. Safari and Firefox will one day (and probably not a particularly distant one at that) roll out support for media queries.

Should that happen, then currently there are 3 hacks that Opera still doesn't get:

  1. :last-child Pseudoclass
  2. :not() Selector with Dummy Attribute
  3. :root Selector

So the relevant CSS could be tweaked something like this (assuming the :root Selector method still works).

div#op8andup-hook-id { background: #0000ff; }
@media all and (min-width: 0px)
	{
	body #op8andup-hook-id { background: #ff0000; }
	:root body #op8andup-hook-id { background: #0000ff; }
	}

Hacking just for Opera 8

Applying a CSS3 selector to the previous example results in a hack that targets just Opera 8. (Hat tip to Philippe Wittenberg for this one)

C1. <div id="op8-hook-id"> ... </div>
This div shows red in Opera 8 but shows blue in all other browsers.
div#op8-hook-id { background: #0000ff; }
@media all and (min-width: 0px)
	{
	body #op8-hook-id { background: #ff0000; }
	body #op8-hook-id[id^="op8-hook-id"] { background: #0000ff; }
	}

Hacking just for IE7

Returning to IE7, until Microsoft fixes the fuzzy specificity bug (it has been reported), you could use it as the basis for a IE7-only flter. The two following rules have the same specificity, but the first one is fuzzily weighted, but only IE7 can see it since it relies on a CSS3 selector.

Z. <div id="ie7-hook-id"><div class="target-class"> ... </div></div>
This div shows red in IE7 but shows blue in all other browsers.
#ie7-hook-id div[class^="target-class"] { background: #ff0000; }
div#ie7-hook-id .target-class { background: #0000ff; }

And more compactly, switching out the parent selector for the omnipresent body element...

Z1. <div class="ie7-target-class"> ... </div>
This div also shows red in IE7 but shows blue in all other browsers.
* div[class^="ie7-target-class"] { background: #ff0000; }
body .ie7-target-class { background: #0000ff; }

You may also want to peruse Brothercake's XXX hack for other ideas.

And yes I do know that the IE7 team strongly discourage the use of CSS filters/hacks and recommend conditional comments instead.

Change Log

7 February 2008
Updated to relect that IE7 turned out the same as IE7b2, and to note the fact that IE8b1 still does the same thing.
16 June 2006
Added Opera 8 specific filter, plus IE7b2 stuff.
Some time ago (er....)
Initial write up of fuzzy specificity and Opera-specific filters.