W3C home > Mailing lists > Public > www-style@w3.org > January 2010

Re: [css3-selectors] Grouping

From: Andrew Fedoniouk <news@terrainformatica.com>
Date: Sat, 09 Jan 2010 18:17:39 -0800
Message-ID: <4B4938C3.4070807@terrainformatica.com>
To: "Tab Atkins Jr." <jackalmage@gmail.com>
CC: Boris Zbarsky <bzbarsky@mit.edu>, Nikita Popov <privat@ni-po.com>, www-style list <www-style@w3.org>
Tab Atkins Jr. wrote:
> On Fri, Jan 8, 2010 at 11:38 PM, Andrew Fedoniouk
> <news@terrainformatica.com> wrote:
>> Tab Atkins Jr. wrote:
>> 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.
> 
> It's clear, I'm just pretty sure it's unnecessary.  Rules starting
> with an #id are pretty common, and a browser could easily match those
> in precisely the method you describe if they wanted to.  You don't
> need special syntax here, because you can reliably detect the most
> common such areas that can use this optimization.

I suspect you still don't get the idea.

Consider <input type="calendar"> element I have:
   http://www.terrainformatica.com/htmlayout/images/datetime.jpg
It is made of ordinary DOM elements like table/tr/td/etc. So
can be restyled on your side.

And now think how you would define styles for it. Typical way of doing
this is to define bunch of styles like:

input[type="calendar"] td { ... }
input[type="calendar"] td:hover { ... }
input[type="calendar"] td:current { ... }

and so on.

As you see you will get bunch of styles ending with the TD in you style
namespace. These rules together with what you will define by your own 
will easily pollute the whole system of styles. *all* other td's in your 
   page have to be tested against these rules.

Consider gmail for example with its thousands of style rules.
Most of them are made from things as I described above.
E.g. single calendar widget create substantial payload for
the whole style system even it is used as a single instance on the
page.

The solution I came up with is to use style sets.
So I am moving all these rules (that obviously apply to elements *only* 
inside input[type="calendar"] element) into the special set:

@set std-calendar
{
   td { ... }
   td:hover { ... }
   td:current { ... }
}

and define input[type="calendar"] as follows:

input[type="calendar"]
{
   style-set: std-calendar;
}

In this case TD elements on the page will be tested
against these selectors
{
   td { ... }
   td:hover { ... }
   td:current { ... }
}

only if these TD elements will get value "std-calendar" in
their style-set attribute.

So no matter how many rules inside @set std-calendar { ... }
you will define they will not affect the rest of your DOM/style
system.

The style sets imply two stages style resolution:

1) First step: elements are getting their styles as usual without
  style sets. So at this point only single rule:
     input[type="calendar"]
     {
       style-set: std-calendar;
     }
  is considered (rules inside set do not affect this step at all
  no matter how many of them you have).

2) Final step: if element gets some value in style-set attribute then 
this element is tested against rules defined in the style set.
In our case only elements inside input[type="calendar"] subtree
are affected - not the whole DOM.

That is why this reduces CPU cycles needed to resolve the whole
style system.

There is only drawback of this schema: all rules inside the style
set override ones you define outside of the set. In short they behave
as if !important is defined for them. In most cases this actually
good thing but sometimes it creates problems. (There is a way to solve 
this problem too)

Beside of the fact that @set feature significantly reduces CPU payload
it is very useful for things like UI components frameworks - usually
component (like calendar above) is a module that has closed and
independent system of styles that has to be applied in "all-or-none" 
manner.
For things like web applications and components @set is the must, IMHO.
We should have something that allow to assemble styles from components
without this O(N*N) problem.


-- 
Andrew Fedoniouk.

http://terrainformatica.com
Received on Sunday, 10 January 2010 02:17:11 GMT

This archive was generated by hypermail 2.3.1 : Tuesday, 26 March 2013 17:20:23 GMT