CSS Selectors not enough
By glazou on Thursday 26 February 2004, 11:05 - CSS and style - Permalink
What I miss the most in CSS ? Clearly, with no doubt, selectors
allowing to select based on children. I have proposed that to the CSS
WG so many years ago. And for the first time, I would need the
:matches() proposal by Ian Hickson... Here's why:
I am working on HTML templates in Nvu. The easiest way to declare a document is conformant to a template is probably
<html templateref="http://glazman.org/templates/glazblog.mzt"> ...
But it's not clean. A clean way of doing it is probably:
<html>
<head>
<title>...</title>
<link rel="template"
href="http://glazman.org/templates/glazblog.mzt"
type="text/html"/>
...
</head>
<body>
...
But that's unfortunately not an option, since I can't apply a style
to body depending on the existence of a link[rel="template"]
inside head... That's very annoying. It can't be
expressed with CSS Selectors, including CSS 3 Selectors. Even with the subject selector, it's not possible.
But with :matches(), that's doable:
head:matches(# > link[rel="template"]) + body
Simple, easy, nice. Unfortunately, that's not available...

Comments
Another way would be just to hardwire the template stylesheet to the documents based on their content (if the <link> element You specified, exists, just apply template stylesheet ).
Right Roland, that's possible. But then you need to watch for that link element all the time. If it goes away, then the document should not treated as template-based any more. It costs an observer, and that's ugly in comparison with the CSS way.
How come Mozilla doesn't support regexp selectors anyway ? I tried to find a bug on it a couple of weeks ago - but there are just bugs on getting image/cookie-blocking by regexp and such.
I prefer the suggestion I made at about the same time. It involves using parenthesis to either indicate the target of the selector, or to alter the way operations are applied, exactly as in infix mathematical notation.
(body) + head > link[rel="template"]
(head > link[rel="template"]) + body
Of course, the first method in this case can't work because the + operator only selects elements that are adjacent and following. On the other hand, can you always rely on the <head> being before the <body>? HTML only requires that they both be descendants of <html>, not on their order.
The reason this isn't being addressed by CSS3 is because of the cost of allowing such selectors, regardless of how they're expressed in CSS. This is explained by Hixie in the linked post. Selectors based on child nodes would require the browser to scan forward into the document to resolve these styles. All the current selectors only need to know about those nodes that have already come in the document. This makes the style resolution algorithms simpler and consequently more efficient. So, this limitation is by design. Not that I haven't wanted exactly this feature myself in the past!
Andrew : yes, I know, I was in the CSS WG at that time. But those selectors could have been restricted to non-interactive media for instance, where progressive rendering and instant answer are far less important than for a browser. Ian and I just discussed today a compromise and I am going to implement it in Gecko as soon as I can. I know how to do that very partial part in a cheap way, NOT having to scan forward but preserving the SelectorMatches() backward scan.
Apologies if I was stating what was obvious to you! If you have the time, please let us know what you do and how you achieve it cheaply; this is very cool stuff!
Looking at this from a totally different angle, I was wondering if you could pre-transform the document (say using XSLT) to spot the <link> and apply a class to the <body>? But that wouldn't deal with dynamic changes, forcing you back down the observer route. Okay... binding XBL to the <body> isn't going to help either, is it? Sorry, stubbornly trying to think of something... I can see why CSS is desirable (from a declarative programming point of view), but are observers really that undesirable?
Of course, you could always just style the <link> itself. Use display: block; and some generated content and you can have a nice header over the body when there's a template.