:nth-child for all descendants

http://smorgbox.dyndns.org/tests/test7.html

I’m looking for a clever trick to select elements either strictly by their nesting depth, or by both ordinal position and nesting depth. In other words, increment n for each nth descendant of an element (or even nth-of-type) rather than just siblings. In the above example I tried and failed to get that RGB sequence to work across depths.

I’ve run across this problem a few times. One practical application might be to alternate between horizontal and vertical CSS menus for odd and even submenus by selecting a ul by nesting depth. I attempted this for a CSS menu but it didn’t quite work. http://smorgbox.dyndns.org/tests/genmenu.html (structure comes from the HTML tree and otherwise uses generated content / counters… fails hilariously in IE of course.)

I don’t really know javascript yet but it would still be interesting to see a pure CSS way.

(first post, hi) :smiley:

Darn! that would be SO useful.

I’ve been wanting parent selectors (and a p0ny) for Christmas for a few years now.

If it were possible to create invisible pseudo-elements and assign attributesp…

I had also been looking around, and it seems they are only selectors… they can find an attribute but cannot create one (that I know of). Javascript can, however, AND JS has (for the most part) Perl-compatible Regular Expressions (minus lookbehinds and atomic grouping or something).

So far as I know, CSS really only goes one-way. I’ve seen mailing lists talking about things like parent selectors, and the argument against them is always that it’s too much work for the browser or two difficult to write specs for. Or something like that. The ability to walk the DOM back “up” is probably why Javascript is used for stuff like this: it can either count siblings/grandparents/whatever, or it can just grab a bunch of elements, loop through them, and use basic math to count out who gets what.
Darn! that would be SO useful. I’m thinking something along the lines of regex “grouping”… like in Python for example where regex_object.group() would pick out a backreference… so with selectors you might go: “group2(span + (div > (p)) a)” to pick out in this case any div and it’s direct descendant if and only if both adjacent to a span and having an anchor as an ancestor. Or… just “group” or “group1” to grab just the p only where it appears in the context of those other selectors.

One thing I’m a bit curious about is whether it’s possible to exploit pseudo-elements for this purpose. Various documents I’ve read hint at the attr() function having quite a bit of power especially in the CSS3 spec. If it were possible to create invisible pseudo-elements and assign attributes to the generated content as “flags” then you could use attribute selectors to read it back in. I’m not sure though if you can use generated content and read back the content with css or both assign and read attributes from pseudo-elements. If you could then this sort of thing might be possible right now. Sucks that “content:” for arbitrary elements still only works in Opera… and I guess ::outside, ::after(n) and friends still aren’t implemented anywhere.

I’m obsessed with this problem! There just has to be a hole in the system somewhere to be abused for some arbitrary Turing-complete computation! :devil:

…It’s partial because it works to crawl down through the levels but not back up - the next element at the top level needs to somehow become aware of the color of the previous element at the deepest level…

So far as I know, CSS really only goes one-way. I’ve seen mailing lists talking about things like parent selectors, and the argument against them is always that it’s too much work for the browser or two difficult to write specs for. Or something like that. The ability to walk the DOM back “up” is probably why Javascript is used for stuff like this: it can either count siblings/grandparents/whatever, or it can just grab a bunch of elements, loop through them, and use basic math to count out who gets what.

Also, I wouldn’t be surprised that, the deeper you nest these rules, the more differences you’ll see cross-browser (for the ones who even support some of these rules… I would be quite happy to have stuff like *:not working everywhere : )

Well I think i’m working towards a very partial and ugly solution to that first example with selectors that kind of look like this:

.box :nth-child(3n+2):not(:empty)>:nth-child(3n+1)

Problem is it requires an exponentially increasing number of rule sets for each added color. With 3 colors it takes 3 additional rule sets per color plus the original 3 totaling 12 to offset the color ordering of each child of a non-empty box.

Still some bugs too. Doesn’t quite work yet for every possible pattern of nesting. It’s partial because it works to crawl down through the levels but not back up - the next element at the top level needs to somehow become aware of the color of the previous element at the deepest level, or the total cardinality of the subsets of the preceding element modulus the number of colors. :confused:

He did say that there was no overhead if the match is unique and you can have as many selectors in front as you like.

I believe the css is applied as elements become available and doesn’t wait until its all finished (otherwise putting the css file at the bottom would not be different to having it at the top but there is a delay if placed at the bottom). Some interesting [URL=“http://stevesouders.com/cuzillion/help.php#examples”]tests here also.

http://stevesouders.com/hpws/rule-css-top.php

[/quote]I hope he goes over things like image loading, that was in a few other threads and seems a place of voodoo : )[/QUOTE]

There was another link I saw here about background images.

Thanks Paul, but the Souders page only repeats re right-to-left, but there’s no mention of CSS going as the DOM is being built. Or I missed it. Or unless that’s what he’s implying when he says a browser looks for all instances of (last/key/right selector) before working backwards. That would make sense (you can’t look for all anchors if the page hasn’t finished loading yet).

The video, I have to wait til there’s time to open VB to run 'blows, but it looks interesting. I hope he goes over things like image loading, that was in a few other threads and seems a place of voodoo : )

Well, when JS does it, the complete DOM is already there. So JS can easily say, give me that element, then give me it’s parent, and then give me the parent of that parent. Because the whole DOM is already laid out, the browser has no problem answering to that request, because it’s only a question of simple looking up in the DOM.

For CSS this is a whole other story, because it has to apply while the DOM is building.

So for example if you have CSS rule like
.something > .somethingelse > .anotherthing {}
the browser has to traverse the partial DOM it has so far upon each and every element it encounters with the class “anotherthing”
Since it doesn’t necessarily have to be the case that every element with class “anotherthing” has a parent with class “somethingelse”, a lot of searches could end up being useless.
This is also the reason why typically you don’t want CSS selectors with more than two descendants (be it a parent-child-relation using > or otherwise).

Does that make sense?

I wouldn’t think that the rendering of the page would have to occur while the document tree is still downloading. CSS doesn’t really seem to deal with the entire DOM but just the data structure formed by the tags of all the content. This might go against how the HTTP protocol works… but if you had just that structure you should be able to process all the CSS without having to wait for things like images and other rich media to download - or irrelevant parts of the DOM to be built. Javascript that generates content by inserting elements I suppose might complicate this though.

Then - I have zero knowledge of browser implementation so surely my view is oversimplified…

The only problem really with CSS parent selectors is how they would be implimented, and also it would cause a lot of strain on the browser to work up the cascade, and surely would hurt loading times, and quite frankly, it’s not what CSS was meant to do Cascading Style Sheets.

There are instances where having parent selectors would make my life 10x easier, though it’s for the best when you think of the downs of having them :slight_smile:

Steve Souders touches on this here.

David Baron explains faster css selectors but this is a long listen.:slight_smile:

The only problem really with CSS parent selectors is how they would be implimented, and also it would cause a lot of strain on the browser to work up the cascade…

What I don’t understand is why it’s easy for JS to do it. It must be how they are actually run in the browser… they’re both working on the same tree (and the browser is their API).

Oh, like my Firefox has :confused:

Because then every browser would suffer from the FOUC bug :wink:

For CSS this is a whole other story, because it has to apply while the DOM is building.

Really? I haven’t heard that (I haven’t heard anything either way about when CSS starts rendering). Why not wait until the document is loaded?

So for example if you have CSS rule like
.something > .somethingelse > .anotherthing {}
the browser has to traverse the partial DOM it has so far upon each and every element it encounters with the class “anotherthing”
Since it doesn’t necessarily have to be the case that every element with class “anotherthing” has a parent with class “somethingelse”, a lot of searches could end up being useless.
This is also the reason why typically you don’t want CSS selectors with more than two descendants (be it a parent-child-relation using > or otherwise).

Isn’t this something entirely separate? I know selectors are read from right-to-left (and so to add to your example, it’s also considered slower to add element names to your tokens:
ul.something > li.somethingelse > a.anotherthing {}
would be even worse; after finding .anotherthing, it then looks “up” to see if it’s an “a” with that class, and so on).

So, it’s looking “up” the DOM, and already checking to see who the parents/ancestors are, so let me use that. If it’s already checking that li.somethingelse is a parent of a.anotherthing, then I should have a parent selector already. I haven’t been able to create a measurable difference between
.something > .somethingelse > .anotherthing {}
and
ul.something > li.somethingelse > a.anotherthing {}
even though one should be slower. It’s likely apparent on very slow systems or connections, or on very large filesizes, but… meh. Likewise I never feel the penalty of *.

Now dynamic pages, I can see where that’s a problem… it’s already a problem for Javascript in some browsers (when changing the DOM, not everyone correctly keeps track of child order etc) and :first-child in CSS. But my hypothetical parent selector would be dealing with a static page.