Re: Proposal: parent selectors

While I'm agreeing with the Implementors' arguments
now I've heard about these, I'm still thinking they are possibly
exagerated.

The :has pseudo-class would not be often used for drastical
changes. So, we're applying :has on elements of the DOM
that doesn't contains many elements. This would 'mitigate'
the problem in most of cases since those elements are not
often subject to DOM changes.

For the other cases, though, it would be possible to build
a sort of cache. When an element is matching a :has rule
(or is only failing a :has part) we add it into a cache list. When
the DOM is modified into an element included in that list, we
check if the element now match the :has rules (or, a contrario,
has stopped to match a :has rule).

Such implementation is possible in JScript, so it's also possible
on the UA side, with the difference the code would be compiled
and optimized.

This would be very efficient, at least if the number of potential
elements matching :has rules is kept small. If not, it may lead
to a higher memory usage, and sightly slow down the page.
But this situation would not occur in 99% of the cases.

Working this way, progressive rendering would continue to
be possible, enven if a "bad" style may be applied until the
"to-have" child is added to the page. But since the :has rule
mostly implies small design changes, this is not a big problem,
I think.

The only way to know it would be to try an implementation,
making some test-cases and returning the results to the mailing
list. This would be an helpful element to close the debate, at
least, if we could prove it really lead to slowness problems.

(BTW, if has-child is acceptable, I don't see any reason why :has
would not be acceptable since has-child also break the UA's CSS
optimisations.)

-------------------------------------------------

Comme use cases would be :
p:has(img), form:has(:focus), .contexMenu:has(:hover), ...

--------------------------------------------------
From: "Eduard Pascual" <herenvardo@gmail.com>
Sent: Thursday, January 21, 2010 5:36 PM
To: "Tab Atkins Jr." <jackalmage@gmail.com>
Cc: "Stephen Belanger" <cyruzdraxs@gmail.com>; <www-style@w3.org>
Subject: Re: Proposal: parent selectors

> *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 18:12:59 UTC