Re: [css3-selectors] Grouping

Tab Atkins Jr. wrote:
> On Fri, Jan 8, 2010 at 10:49 PM, Andrew Fedoniouk
> <news@terrainformatica.com> wrote:
>> Boris Zbarsky wrote:
>>> On 1/8/10 12:33 PM, Nikita Popov wrote:
>>>> Which would lead to 3^4 = 81 rules. Hopefully nobody does it.
>>> Sure they will.  That's just life.
>>>
>>> On the other hand, it's not like stylesheets have small numbers of rules
>>> as it is.  gmail has several thousand, for example....
>>>
>>> The biggest danger here, actually, as with any compression scheme, is
>>> being a vector for DOS attacks.  And honestly, those are just possible
>>> already: you could gzip-compress your stylesheet with lots of redundant
>>> rules and it would end up very small to transmit but huge to parse and such.
>>>
>> I have mentioned once already that I've implemented so called style sets (in
>> HTMLayout and Sciter).
>>
>> The set is defined as (same syntax as @media section):
>>
>> @set somename
>> {
>>  ... rules ...
>> }
>>
>> and is applied by the style-set CSS attribute.
>>
>> Using sets original task of reducing these 6 rules:
>>
>> #authors input, #authors select, #authors textarea,
>> #publications input, #publications select, #publications textarea
>> {
>>  ... rules ...
>> }
>>
>> could be rewritten as:
>>
>> @set my-section
>> {
>>  input, select, textarea
>>  {
>>     ... rules ...
>>  }
>> }
>>
>> #authors, #publications
>> {
>>  style-set: my-section; /* style-set is an inheritable attribute
>>                            all elements inside #authors will also use
>>                            rules defined in the my-section */
>>  ...
>> }
>>
>> This approach has following benefits:
>>
>> 1) Style rules declared inside the @set are shielded from normal process of
>> assigning styles. So they are not creating additional payload.
>> Problem "3^4 = 81" simply does not exist in this approach.
> 
> I truly don't understand this.  You're still doing precisely the same
> amount of matching work.  In this case, you still have to verify that
> an element is an input with an #authors ancestor, or an input with a
> #publications ancestor, or a select with an #authors ancestor, etc..
> Effectively you still have 6 selectors there.  You *cannot* reduce
> this amount of work without transforming the document itself.
> 

Consider that you have DOM of 1000 elements and these two style rules:

.foo { color: red; }
.bar { color: blue; }

style resolution procedure for the DOM will scan all 1000 elements
and check if any of them have foo or bar class. So in total this
would be 2000 comparisons. Most of them are usually misses (negative 
test result) but still.

Now imagine that you have these two rules enclosed into the set:

@set FooSet
{
   .foo { color: red; }
   .bar { color: blue; }
}

This will exclude .foo and .bar rules from style resolution procedure.
Effectively this is like you have no styles defined at all.

Now let's imagine that we have some container in the DOM with id = 
#publications. Say it contains 100 DOM elements (from total 1000).

Let's add following rule for such a container:

#publications
{
   style-set: FooSet;
}

and run the same style assigning procedure:

900 elements will be skipped - no ordinary rules at all.
100 elements will have style-set defined and only for these
elements these two selectors will be checked ( .foo and .bar)

So you will have:

   1) 200 checks of selectors (instead of 2000)

   2) For compound selectors checks will be made for the depth of
      subtree (from #publications element here) - not full tree.
      This reduces needed CPU cycles too.

Let me know if idea is clear enough.


>> 2) Set of style rules is used on all-or-none basis - it is enough
>> to redefine:
>>  #publications.special
>>  {
>>    style-set: my-special-section;
>>  }
>> and the whole set of rules for the sub-tree will be redefined
>> as a whole.
> 
> It is similarly simple to say
> 
> #publications.special :matches(input,select,textarea) {
>   //new rules
> }
> 
> With the same effect.
> 

No. Effect is not the same. For each of 1000 DOM elements you should
execute at least following check:

   if( element.tag == input ||
       element.tag == select ||
       element.tag == textarea )

So in total at least 3000 checks by introducing just one (as author will 
think) CSS rule. Yes, element.tag == input is a cheap operation but 
still it should be made.

And if you will go for something like

#publications.special :matches( :has-child(input),
              :has-child(select), :has-child(textarea))

you will get perfect combinatorial explosion.


-- 
Andrew Fedoniouk.

http://terrainformatica.com

Received on Saturday, 9 January 2010 05:37:58 UTC