Universal Child Replacement
Published 21 years, 5 days pastThe other day I hit a situation that pushed me to come up with a way to simulate the child selector in a way Internet Explorer could understand using two rules. I doubt I’m the first to think of it, but I’d never seen it before, so I thought I’d document the solution here.
The deal was that I had a column of text featuring white background with some black flecks in it. On top of that went some near-black text. All fine, except where the text sat on top of a fleck, which made it next to impossible to read.
To counteract that effect, I decided to set the background of the various descendants of that div to be white, so they’d mask any flecks they were overlapping. Thus I wrote:
#main * {background: #FFF;}
It worked great for about a second. That’s when I realized that I had links in the column, and some of them were sitting inside table rows with a non-white background. The rule I’d just written was giving the links white backgrounds, which had the visual effect of punching holes in the row backgrounds. That was no good.
What I really needed was a way to just set white background on elements that were children of #main. CSS has a child selection combinator (>) but neither version of Internet Explorer supports it. After a few moments’ thought, I realized that I could add a rule that would make transparent the background of any element that was at least a grandchild, but not a child, and it would still work in Explorer.
#main * {background: #FFF;}
#main * * {background: transparent;}
The end result is that there is a way to simulate child selection without actually using the child combinator. The general pattern is to use a normal descendant selection in your first rule, and then “undo” the first rule with a second that has a universal selector in the middle. Suppose you want to boldface any p element that’s a child of a div, but no others. The solution:
div p {font-weight: bold;}
div * p {font-weight: normal;}
It might not be something you use every day, but if it’s needed, there you go.
Update: Lachlan points out that you’ll need to watch out for specificity conflicts when using this technique.
In Safari, you see, the caption’s element box is basically made a part of the table box. It sits, effectively, between the top table border and the top margin. That allows the caption’s width to inherently match the width of the table itself, and causes any top margin given to the table to sit above the caption. Makes sense, right? It certainly did to me.
This is the behavior evinced by Firefox 1.0, and as unintuitive as it might be, it’s what the specification demands.