- From: Tab Atkins Jr. <jackalmage@gmail.com>
- Date: Wed, 15 Oct 2008 10:30:02 -0500
- To: Simetrical <simetrical@gmail.com>
- Cc: "Keiji Ikari" <kei@teamikaria.com>, "W3C Style List" <www-style@w3.org>
- Message-ID: <dd0fbad0810150830w7bf25b9bib9a5d68dd87e2b2a@mail.gmail.com>
On Fri, Oct 10, 2008 at 10:08 AM, Simetrical <simetrical@gmail.com> wrote: > On Thu, Oct 9, 2008 at 9:48 AM, Tab Atkins Jr. <jackalmage@gmail.com> > wrote: > > The discussion spawned off of that thread [1] between me and Boris, > though, > > came to the conclusion that a simple parent selector wouldn't be overly > > burdensome (a previous-adjacent-sibling selector would be worse, a > > previous-sibling selector worse still, and an ancestor selector worst of > > all). It can cause reflowing, but the damage is relatively limited (to > only > > the parent and any siblings+children), and the computational hit of > > computing matches is minor in this simple case. > > > > [1]:http://lists.w3.org/Archives/Public/www-style/2008Jul/0603.html > > His answer was kind of noncommittal, I think: > > > For "foo:matches(> bar)", if that means "a <foo> which has a <bar> > > child" that means that in genera we need to reresolve the parent of a > > node being inserted or removed (plus of course all its descendants). > > This can be optimized a bit by keeping track of whether such a :matches > > is around and would have to be, because adding children to an > > <html:body> is pretty common during parsing. > http://lists.w3.org/Archives/Public/www-style/2008Jul/0625.html > > The basic point is that for DOM appends, you have to re-render one or > more elements for all these selectors, or else delay progressive > rendering. The parent selector could be unpleasant if you were doing > something like "body:child(div.myclass)" and that got hit late in a > long document, whatever you do. Until everyone has a lot more > CPU/network bandwidth and everything parses instantly, maybe. :) > (But "adjacent sibling" is automatically limited to having to > reflow/delay for only one element, so it's probably more feasible: > "pretty easy" and "doesn't sound too bad", as Boris said.) Yup, that's what I got out of it too. Of course, when an implementor tells me something would be "pretty easy", I tend to take that as a good sign. ^_^ At least when applied to a proposal like this, which has been talked about like it was impossible for forever. Yes, any sort of :matches or :child selector hooked off of the body element would be non-optimal, but honestly, do people really *do* that? The only time body shows up in my selectors is when I'm setting the base font details or the overall background for the page. I suppose you could try to be fancy and change the page background based on some element within the page, but you're really just *asking* for a reflow at that point - a javascript-based solution would be just as bad. As well, this scenario becomes even less likely when you consider that we're only allowing the child combinator here, so this body-level change would have to key off of the uppermost level of elements, which is typically just a bunch of containers for the page. I think a couple of more limited variants could be implemented > cheaply, though. For instance, "an X whose *first* child is a Y" > should be no problem at all: just don't begin rendering the element > until you've got the opening tag of its first child, which should be > just about immediately. That certainly would work. I'd bet it'd be nearly trivial. > This might work in a considerable percentage > of use-cases for a general parent selector. You might even be able to > do "an X whose 'first descendant' is a Y", so a hypothetical > "div:first-descendant(input)" would match the outermost div of > > <div><fieldset><input ...></fieldset></div> > > again, I hope -- not being too savvy on the implementation of such > things -- without much cost. The point would be to not allow any text > or other stuff that actually needs to be rendered in between the tag > you're actually matching and the opening tag you're checking for. You > wouldn't have to reflow anything, and I'm guessing you wouldn't > significantly delay progressive rendering. Hmm, yeah. This would likely be only slightly less trivial. One issue with it is that it's sensitive to empty text nodes as written, which means you're restricted in how you're allowed to indent your code. I'd make sure it was stated that empty text nodes are ignored for this purpose. I guess you might have to wait a bit longer to start drawing borders > and so on, things that only depend on the outer element -- you'd have > to wait for the opening tag(s) of the next element(s) to be parsed. > But a) it should be a very short wait in any remotely reasonable case > (yeah, str_repeat( '<div>', 50000 ) would be slow, granted), and b) I > don't know how common such things are anyway -- in many cases you'd > have to wait for at least the beginning of the element's contents to > be able to start drawing any of it anyway (e.g., you can't draw the > background of a typical empty div, since it will be zero-height until > it has contents). Yup. From what I know of rendering (little, but I learn more every thread), this wouldn't be an issue. > What were the use cases given for a parent selector again? The one > that springs to mind is things like styling wrappers differently if > they contain form controls, as in my example above, which this weaker > (and faster?) variant might well allow in many cases. In general, styling wrappers based on their content. In specific, form controls have been batted around as a common subcase, and I know that I've written code that would benefit from this for exactly that reason (specifically, I've many times wanted to style a wrapper based on the :selected status of its contents). The limited form of child and descendant combinators would indeed work well for a majority of cases here. I suppose that maybe we want to split this off into multiple pseudoclasses, then. To start with, we have :first-child() (obviously this is a bit confusing with the existing :first-child pseudoclass, but are the parenthesis enough to disambiguate adequately?), :first-descendant(), and :first-sibling(). All of these take simple selectors in thir parentheses. The first two match as you've described here, where the selector has to match against the very first child, or the very first rendered descendant (that is, no content can come between the parent and the matched descendant). :first-sibling() would just match if the next sibling is matched, in accordance with my previous proposal for :matches( + div ). If it is deemed feasible, then, we can introduce a :child() pseudoclass. It was said that it's probably infeasible to do a general sibling or descendant forward-matcher, but if/when it *does* become possible, we can introduce the :sibling() and :descendant() pseudoclasses as well. Should these go into the spec from the start, with the understanding that current UAs probably won't implement them? Or is it better to leave them out and add them back in when UAs say they're ready for them? If the latter, I recommend a note in the spec saying approximately that these pseudoclasses, while an obvious addition, aren't currently feasible to implement. That should maybe prevent a constant flood of people asking why such obvious additions aren't in the spec. ^_^ So, implementors, thoughts? :first-child(), :first-descendant(), and :first-sibling() are probably okay to implement, right? Any thought on :child() from the Webkit or IE team? ~TJ
Received on Wednesday, 15 October 2008 15:30:43 UTC