- From: Eduard Pascual <herenvardo@gmail.com>
- Date: Thu, 21 Jan 2010 17:36:12 +0100
- To: "Tab Atkins Jr." <jackalmage@gmail.com>
- Cc: Stephen Belanger <cyruzdraxs@gmail.com>, www-style@w3.org
*That* discussion again... Another CSS user asking for a feature, so another proof there is a need for it. We are getting the same arguments as before (the "too ineficient" one), and it is as invalid as before. Fact #1: whatever that can be achieved through jQuery, could be done faster through a native implementation within the UA. Proof: jQuery essentially is an API written with an interpreted language (JavaScript) on top of the native APIs provided by the UAs. So, whatever a page does through jQuery, it's broken down and deferred into calls to the UA's API, which in turn performs the task through the native UA code that implements the API. So, if the UA provided the feature natively, we would save an indirection step (from jQuery's APIs to the UA's APIs), plus the overhead of JS code parsing/interpretation. Issue: UA vendors are obsessed with absolute progressive rendering, which on the general case comes more from historical reasons (remember when we had to wait for an entire page to download over a 14Kbps line before we could see anything on the screen?) than from a current need. Sure, for large enough pages progressive rendering can still be noticed; but even in that case, it's often not enough: big pages often use complex layout, with an insanity of floats, tables, and what-not that keep moving around the screen until a significant part of the page is loaded. Yet, users don't tend to complain about this: they see that something is going on, and at the end they intuitively understand that it took a bit longer because of the lot of stuff that's in there. All of this leads me to the following point: Question: if :has() (or any equivalent feature regardless of syntax) was implemented, would it need to take profit of progressive rendering? Answer, Fact #2: No. Proof: Those authors who really need :has()'s functionality rely on jQuery, so they don't get progressive rendering. It's a trade-off, and the volume of web authors relying on jQuery are a proof that it's a good deal on many cases. Even for newbie authors who don't understand the efficiency costs of this feature, if they have a minimum idea of what they are doing they'll test their pages on at least one browser, so they'll get an idea on how fast or slow they load. Based on the above, here it goes: Suggestion for UA vendors: implement some version of this feature experimentally (maybe a limited version, such as the "child" and/or "next-sibling" versions that have been discussed previously), with vendor prefixes or whatever, that defers processing of rules using this feature until the rest of the document has been loaded. The rules can be flagged for deferred execution as soon as the ":has(" string (or whatever other syntax they use) is found on the selector, and elements that would match the part of the selector before ":has(" could also be flagged so style updating after dynamic modifications of the page can be optimized. In summary: - Authors that use jQuery seem to be ok with the efficiency costs of jQuery's features (otherwise, they wouldn't be using it). - Whatever that can be done through a javascript library could be done faster if implemented natively by the UA. -> Based on the two points above, the efficiency arguments against :has() (or :matches(), or <, or :has-child(), or any other of the many syntaxes that have been proposed until now) become worthless. The only thing I'm asking vendors to do (and without almost no hope of being listened anymore) is to simply try it, and then decide whether it's worth or not. Regards, Eduard Pascual On Thu, Jan 21, 2010 at 3:26 PM, Tab Atkins Jr. <jackalmage@gmail.com> wrote: > On Wed, Jan 20, 2010 at 1:11 PM, Stephen Belanger <cyruzdraxs@gmail.com> wrote: >> This has probably been suggested before, but I didn't find it in a search. >> Currently we can find child elements like so; >> a > img >> This would return any image contained in a link--but what if you need to >> select any link containing an image? For that I propose an equivalent that >> runs in the opposite direction; >> img < a >> The css interpreter would start by finding all 'img' elements, then it would >> try to move one level up and, if an 'a' element is found, would return >> successful and add that element to the list of elements to apply that >> particular style to. > > Yup, been discussed before. ^_^ It's a difficult problem, though. > > The general case is implemented in jQuery by the :has() pseudoclass. > You'd write "a:has(img)" to select an a that has an img descendant, or > "a:has(>img)" to be more specific about where the image is. > > Unfortunately, while this is reasonable to implement once you have the > entire page built and ready like jQuery does, it breaks some very > important optimizations if you're trying to match selectors to > elements *while* the page is being built, which is the time when > browsers do the majority of their selector matching. Basically, with > normal CSS you have all the information you need to find all the rules > that match an element as soon as the element appears; if you start > from the end of the selector and go backwards, you keep looking for > parents, ancestors, and previous siblings, all of which occur earlier > in the code and thus have already been parsed and inserted into the > page. :has() breaks this, as it requires information about > descendants and later siblings, which means you can't match the rule > to an element until well after it's been parsed. > > So, :has() is very inefficient. It's also very useful, though, so > it's certain to show up in CSS at *some* point. > > For now, though, Boris Zbarsky of Mozilla has indicated that a > :has-child() pseudoclass wouldn't be *too* inefficient, and so I > believe it's likely to show up in Selectors Level 4 (we've finished up > Level 3 already, and are pushing it through the standards track now). > I think :has-child() covers the majority of use-cases as well - my > main need for it is "label:has-child(:checked)", and your > "a:has-child(img)" would also work. > > ~TJ > >
Received on Thursday, 21 January 2010 16:37:05 UTC