IE7 Uncle Double Class Selector Bug by Mit The Destroyer
While debugging some code on a site I work on. I discovered a new double class bug in IE7. The weird thing about it is the code that causes the double class bug to appear is not even related to it. Sample Test case:
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” xml:lang=”en” lang=”en”>
<head>
<title>IE7 Uncle Double Class Selector Bug</title>
<meta http-equiv=”Content-Type” content=”text/html; charset=iso-8859-1″ />
<meta http-equiv=”Content-Style-Type” content=”text/css” />
<style type=”text/css” media=”screen”>
p {
color: red;
}
.class1.class2 p {
color: green;
}
.foo + p { }
</style>
</head>
<body>
<div class=”class1 class2″>
<p>I’m Green</p>
<p>I’m Green Too</p>
</div>
<p>I’m red</p>
</body>
</html>
I’ve set all paragraphs to default to the color red. However, due to the double class selector changing its children’s paragraphs to green, and also creating a select any element that has the class foo, whose siblings are paragraphs (doesn’t matter if you set styles or not in that selector, or if the .foo is changed to * or to an element selector that is the same element as the parent with the double class selector [e.g. * + p {}, or div + {}]) it will cause IE7 to create a symbiotic relationship between “.class1.class2 p:last-child” and “.class1.class2 + p:first-of-type”. Thus, if you set styles on “.class1.class2 + p:first-of-type” it will cause “.class1.class2 p:last-child” to get those same styles (and visa versa). Luckily there are a couple work a rounds (ordered by effectiveness).
- Don’t use any sibling selectors in your styles
- Add any type of DOM node between .class1.class2 and it’s sibling p, so long as it’s not a plain text node (e.g. you can use a comment tag or empty element node with style set to display: none;).
- Add an inline style declaration on the effected element that overrides the style set on the “.class1.class2 p” selector.
- Change the “.class3 + p” selector to be an element + p selector, so long as the element to the left of the + is not the same element type that would get selected by the double class selector. In other words with the test case above you can use any element + p combination except for div + p
- Change the “.foo + p” selector to ” #foo + p” selector
- Change the double class selector to a single class selector (e.g. change “.class1.class2 p” to “.class2 p” or “.class1 p” (this solution only works so long as you don’t have any * + p selectors).
