W3C home > Mailing lists > Public > www-style@w3.org > December 2003

RE: CSS3 Selector Limitations and Suggestions

From: Ernest Cline <ernestcline@mindspring.com>
Date: Sun, 7 Dec 2003 13:17:40 -0500
Message-ID: <410-220031207181740906@mindspring.com>
To: "Lachlan Hunt" <lhunt07@netscape.net>, www-style@w3.org




> [Original Message]
> From: Lachlan Hunt <lhunt07@netscape.net>
> To: <www-style@w3.org>
> Date: 12/7/2003 7:03:27 AM
> Subject: CSS3 Selector Limitations and Suggestions
>
>
> Hi,
>   While experimenting with XHTML2, I have discovered some limitations 
> with CSS.  Based on these I have come up with a few proposals for CSS3.  
> Sorry for making this long, but I have put a lot of effort and thought 
> into this and tried to be as clear as possible.
>
> -- XHTML 2 Example --
>
>   Throughout this post, all my CSS examples will apply to this XHTML 2 
> fragment:
>
> <body>
>     <section>
>         <h>Heading 1</h>
>         <div>
>             <section>
>                 <h>Heading 1.1</h>
>             </section>
>         </div>
>         <section>
>             <h>Heading 1.2</h>
>             <section>
>                 <h>Heading 1.2.1</h>
>             </section>
>         </section>
>     </section>
> </body>
>
>
> -- Limitations --
>
> 1. There is no easy way to select a specific section level because
>    other block elements may appear between, with just one selector.
>    eg. In the above example, with the <div> appearing before the first
>    second level section (1.1), but not the second (1.2), the following
>    cannot be used:
>
> body > section section > h {
>     /* Selects both 2nd and 3rd levels
>        (1.1, 1.2 and 1.2.1) */
>     color: green;
> }
>
> body > section > section > h {
>     /* Does not select Heading 1.1
>        Only selects Heading 1.2 */
>     color: red;
> }
>
> 2. There is no shorthand method for selecting the nth descendant level
>    of an element.  eg. shorthand for selecting the 6th level section:
>    body > section > section > section > section > section > section
>    which also has the problems of the above limitation.
>
>
> -- Proposals to Solve these Limitations --
>
>   I have come up with two potential solutions.  One using a combinator 
> and the other using pseudo classes.  I think the pseudo classes are more 
> flexible, but the pseudo classes may be easier to understand, after 
> understanding the concept of the combinator.
>
>
> -- Combinator --
>
>   Just as there are direct adjacent '+' and indirect adjacent '~' 
> sibling combinators, I propose there be an indirect descendant 
> combinator to pair with the child combinator '>' (since a child element 
> is a simply a direct descendant)
>
>   This would differ from the normal descendant selector (white space) in 
> that it would only select the first matching descendant element 
> regardless of any nested elements between such as the <div> in the above 
> example.
>
>   I'll use the symbol '^' to represent this because of it's similarity 
> in shape to the child descendant selector '>', and also because it kind 
> of represents a simple tree structure like xml (though with only 2 
> branches), but the symbol doesn't really matter.
>
> body > section ^ section {
>     /* This selects Headings 1.1 and 1.2,
>        but NOT Heading 1.2.1 */
> }
>
> * Advantages
>   Very simple and effective
>
> * Disadvantages
>   Not very flexible.  For example: can't select the last, or last of 
> type, descendants in the tree.  For example, selecting both sections 1.1 
> and 1.2.1.

An interesting idea, but is it likely to come up much in actual practice?

The effect I believe you are looking for with this selector can be
achieved with existing selectors:
body  section section:not(body section section section)
would select just the second level sections in this case

> -- Pseudo Classes --
>
>   Just like there are :nth-child(n) and :nth-of-type(n) pseudo classes 
> that apply only to children of the same parent, I think it would be 
> useful if there were :nth-descendant pseudo classes as well that apply 
> to descendants of the same ancestor, following the document tree.
>
>   There are eight pseudo classes that I'll introduce, which I have 
> derived from the :nth-, :nth-last-, :first- and :last-child() and 
> -of-type() pseudo classes, and applied to descendants.
>
>   I believe these pseudo classes can only be effective when used with 
> the descendant selector (white space).  My use of the term 'descendant 
> level' means the number of descendant elements along any given path.  If 
> an equivalent term has already been used in CSS, then it should be used 
> instead.
> eg.
> <x>
>     <y/>
>     <z/>
> </x>
>   The <x> element only has one descendant level, even though there are 
> two children
>
> <x>
>     <y>
>         <z/>
>     </y>
>     <z/>
> </x>
>   This <x> element now has two descendant levels.
>
>
> - Descendant Pseudo Classes -
>
> * :nth-descendant(an+b)
>   The :nth-descendant(an+b) pseudo-class notation represents
>   an element that has exactly an+b-1 ancestors in the document tree,
>   which are also descendants of any specified ancestors, for a given
>   zero or positive integer value of n.  If no ancestors are specified,
>   then the root element is used.

This can be done using the :rpt() pseudo-class you give later,

E F:nth-descendant(an+b)
is equivalent to:
E > *:rpt(an+b-1) > F

> * :nth-last-descendant(an+b)
>   The :nth-last-descendant(an+b) pseudo-class notation represents
>   an element that has exactly an+b-1 descendant levels in the
>   document tree, for a given zero or positive integer
>   value of n.

Can you give a use case of  why one would want this selector?
You gave an example of how it would be used, but not why.

> * :first-descendant
>   Same as :nth-descendant(1), but with a lower specificity.
>
> * :last-descendant
>   Same as :nth-last-descendant(1), but with a lower specificity.
>
>
> - Descendant of Type Pseudo Classes -
>
> * :nth-descendant-of-type(an+b)
>   The :nth-descendant-of-type(an+b) pseudo-class notation represents
>   an element that has exactly an+b-1 ancestors with the same
>   element name in the document tree, which are also descendants of
>   any specified ancestors, for a given zero or positive integer
>   value of n.  If no ancestors are specified, then the root element
>   is used.

This can also be done using the :rpt() pseudo-class you give later,

E F:nth-descendant(an+b)
is equivalent to:
E  *:rpt(an+b)

> * :nth-last-descendant-of-type(an+b)
>   The :nth-last-descendant-of-type(an+b) pseudo-class notation
>   represents an element that has exactly an+b-1 descendant levels with
>   the same element name in the document tree, for a given zero or
>   positive integer value of n.

Again, can you give a use case of  why one would want this selector?
You gave an example of how it would be used, but not why.

> * :first-descendant-of-type
>   Same as :nth-descendant-of-type(1), but with a lower
>   specificity.
>
> * :last-descendant-of-type
>   Same as :nth-last-descendant-of-type(1), but with a lower
>   specificity.
>
>
>   For the :nth-descendant(an+b) pseudo classes, when an+b = 1, it may 
> appear to be equivalent to the :first-child or nth-child(an+b) pseudo 
> classes, however, these classes will only select one matching child, 
> whereas nth-descendant(1) will select all matching children.  I nearly 
> made this mistake myself, so I want to make sure everything is as clear 
> as possible.
>
>   I have tried to be as accurate as possible with my definitions, but I 
> still may have made some minor mistakes.  If in doubt, the following 
> examples illustrate their intended meaning.
>
>
> -- Examples --

<snipped examples>

> -- One Final Pseudo Class --
>
>   This is directly related to limitation 2 from the beginning.  A 
> shorthand method for specifying repeating selectors like:
>    body > section > section > section > section > section > section > h
> could be something like
>
>   body > section:rpt(6) > h
>
> Possible definition:
>   The rpt(0n+b) pseudo class is a functional notation which copies the
>   selector up to and including the previous combinator, and is
>   repeated, or multiplied, n times, for any positive, non zero value
>   of n.
> (If a value of 0 was allowed, it would mean that the selector would be 
> removed)

A repeat selector mechanism would make things easier,
altho I'm not at all happy with the proposed syntax.

> -- Conclusion --
>   I think the pseudo classes will add a lot of flexibility to the CSS 
> language.  Even though my examples deals specifically with the
> XHTML2 example, there is no reason that they cannot be applied
> to any form of  XML document.

I think adding one single mechanism to handle repeating portions of
a selector using the (an+b)  mechanism of nth-child to choose the number
of repeats would add most, if not all, of the flexibility of what you are
looking for here without adding so much to CSS.  In any case since
CSS3 Selector has been in CR for over two years and is scheduled
to shortly become a REC according to the roadmap, I think it is safe
to say that at soonest, this might be added as part of CSS4 Selector.
Received on Sunday, 7 December 2003 13:17:41 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Monday, 27 April 2009 13:54:25 GMT