Almost two years ago I called out for a new combinator. Not many people
warmed up to the idea, so I left it at that. Sadly these past couple of
months I've been experiencing more and more issues that all link back to my
original post.
The problem:
What I would like to do is find a way to style a component somewhat
separately from its (nested) context. Let me start with a little code
example:
<article class="product>
<header>.</header>
<div class="main">
<article class="review">
<header>.</header>
.
</article>
</div>
</ article>
A simple piece of html for a product with reviews nested inside its main
content. The difficulty here is properly styling the header elements. Surely
it's not interesting for the review header to inherit the styles of the
product header, so we try to keep the styling separate:
article.product > header {..}
article.review > header {.}
This should do the trick for the code above. But setting your css so
strictly on html code can become real troublesome. Here are two examples
that will completely destroy your css:
1/ suddenly they decide to make every product appearing in a list to be
fully clickable. What you do is wrap header/main/footer in an <a>. Your css
breaks as you've killed the parent/child link between base tag and header.
You can add the a element to the css selectors, but this will break all css
for the detail view (which does not need the block-level link)
2/ javascript! It's pretty common these days to add all kinds of extra
structural elements for components. You write the basic html for people who
don't have javascript enabled, and add the extra elements in javascript for
those that have it enabled. But adding structural elements (especially
wrappers) can completely break your css. This sucks if you're using an
existing javascript, but even when you're writing it yourself you're still
forced to duplicate selectors when a child selector breaks.
These two cases are hardly uncommon and I've encountered them quite a few
times these past couple of months, forcing me to curse even more than I
already did before, mostly because I had hoped that when dropping ie6 things
would've become more robust to style.
The (partial) solution
Translating my need to a practical solution may not be all that easy. The
closest I get is looking for the first nested instance and target all
matches on that level:
article.product (?) header {.}
This should match the first nested instance of the header, ignoring whatever
levels that come in between .product and header, but failing to match the
header in article.review
Problems with the solution above
I know this is not a full fix for my problem. If I have <p> elements nested
on several levels nested inside the article.product I still can't style them
differently from the <p> elements inside the article.review. This would call
for a way where css could define an actual scope. While I think this could
be incredibly powerful, it's also destructive in the wrong hands.
Still I believe that the extra combinator could solve a lot of problems,
even in its somewhat defected form. With more and more scripts changing the
html code and with functional elements like <a> and <form> around that can
break the structure (while they should not really influence general styling)
I believe that the child combinator is becoming increasingly dangerous to
use, hence becoming more and more useless. This is a shame because it's
essential in styling elements separately from its context.
Finally, the blog post I wrote almost two years ago:
http://www.onderhond.com/blog/work/missing-css-combinator
Greets,
Niels Matthijs
http://www.onderhond.com