Re: a recall for a missing combinator

On Tue, Nov 15, 2011 at 12:44 AM, Niels Matthijs
<niels.matthijs@internetarchitects.be> wrote:
> <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

I approve of this.  Let's call it the "closest descendant" combinator.
 Perhaps it could look like ">>".

Both of your use-cases are reasonable and things that I have run into
before.  You definitely don't want to use the descendant combinator in
your example, as it would "pollute" the lower header and possibly
force you to manually revert some properties just because the upper
header used them.

The performance story should be fine.  It's like the descendant
combinator, except when you're walking up the tree to find the
ancestor, you *also* look for someone else that matches the
descendant.  If you find the latter before you find the former, the
selector doesn't match.  The optimization strategies we're now
employing to speed up the descendant combinator should reasonably
apply to this as well.

This also plays very nicely with the subject indicator to emulate the
functionality of jQuery's .closest() method, which I used *constantly*
back when I used jQuery.  "el.closest('foo')" translates to
"el.find('?foo >> :scope')".

~TJ

Received on Tuesday, 15 November 2011 15:50:13 UTC