W3C home > Mailing lists > Public > www-style@w3.org > July 2008

Re: Opera's Proposal for :context Selector

From: Tab Atkins Jr. <jackalmage@gmail.com>
Date: Mon, 14 Jul 2008 16:46:20 -0500
Message-ID: <dd0fbad0807141446l2fb4de40v65f4da4d8821587d@mail.gmail.com>
To: "Andrew Fedoniouk" <news@terrainformatica.com>
Cc: "Lachlan Hunt" <lachlan.hunt@lachy.id.au>, www-style <www-style@w3.org>

On Mon, Jul 14, 2008 at 4:18 PM, Andrew Fedoniouk
<news@terrainformatica.com> wrote:
> Tab Atkins Jr. wrote:
>>
>> Grr, misused the tab key.  Continuing message...
>>
>>
>>
>>  On Mon, Jul 14, 2008 at 2:50 PM, Andrew Fedoniouk
>> <news@terrainformatica.com> wrote:
>>
>>>
>>> Thanks for your answers, your intention is more clear now but see
>>> below...
>>>
>>> Lachlan Hunt wrote:
>>>
>>>
>>>>
>>>> As a proof of concept, consider this example:
>>>>
>>>> <body class="foo">
>>>>  <section>
>>>>   <style scoped>
>>>>   .foo h1 { color: green; }
>>>>   .bar h1 { color: blue; }
>>>>   </style>
>>>>   <h1>Example</h1>
>>>>   <p>Hello world!</p>
>>>>  </section>
>>>> </body>
>>>> This allows styles to be changed dynamically by changing the class name
>>>> on the body element from "foo" to bar", which would change the heading from
>>>> green to blue.
>>>>
>>>
>>> You already can do that. Simply write:
>>>
>>>  body.foo h1 { color: green; }
>>>  body.bar h1 { color: blue; }
>>>
>>> and it will work for you already. Why do you need <style scoped> then?
>>>
>>
>>  The two work quite a bit differently.  Your selectors will match (and
>> change the color of) *all* <h1>s in body.foo or body.bar.  The scoped
>> stylesheet *only* changes those <h1>s that appear within the <style>'s
>> scope.  <h1>s that appear elsewhere will not be affected, even though
>> they may match a naive application of the selector.
>>
>> The same applies to the querySelector, but you already get that (you
>> said exactly what is meant - that it's a global selector but against a
>> limited set of elements).  The two are meant to work the same.
>>
>
> Ok.
>
> To achieve reliable results you always have to put full path in selectors:
>
> <body>
>   <div id="scope">
>     <style scoped>
>        .foo #scope h1 { color: green; }
>        .bar #scope h1 { color: blue; }
>    </style>
>    <div class="foo">
>      <h1>header</h1>
>   </div>
>  </div>
> </body>
>
> even in scoped style sheets.
>
> So why do you need that word "scoped" in the <style>?
>
> Construction above will work without scoped too:
>
> <body>
>   <div id="scope">
>     <style>
>        .foo #scope h1 { color: green; }
>        .bar #scope h1 { color: blue; }
>    </style>
>    <div class="foo">
>      <h1>header</h1>
>   </div>
>  </div>
> </body>
>
> Will lead to exactly the same results. So why? What prevents you from using
> that way scoped style sheets now?

Ah, I see.  Your issue here is that you don't understand the primary
use of <style scoped>, which is to perform a limited sandbox on the
styles.  For example, say you ran a social network and wanted the
users to be able to style their individual pages.  However, you want
to enforce a common template that the users *can't* change.  If you
wrap their CSS in <style scoped> and place it appropriately, they
can't have any effect on your site template, but are still free to go
wild on the CSS of their personal section.

>
>>
>>>
>>> As far as I understand intention is to have:
>>>  <style scoped src="style-system-for-my-component.css" />
>>> and to be able to use that style-system-for-my-component.css in various
>>> places/pages?
>>> Modularity implies that declarations in style-system-for-my-component.css
>>> are
>>> independent from the position of scope/root element on the page - rooted
>>> to the element
>>> this style set is applied to. So you could share your
>>> libraries/components.
>>> Too bad if this is not the intent.
>>>
>>
>> I agree here, though, that *without* a :scope or :context pseudoclass,
>> it can be difficult to achieve proper modularity.  Frex, in this
>> fragment:
>>
>> <section>
>>  <style scoped>
>>    div span { color: red }
>>  </style>
>>  <span>span content</span>
>>  <div>
>>    <span>some more span content</span>
>>  </div>
>> </section>
>>
>> The second span will definitely be red, but the first will be red
>> depending on whether or not there is a div somewhere further up the
>> ancestor chain.
>>
>> In other words, I *really like* having querySelector and scoped
>> <style>s do a global match (but only apply to a limited set of
>> elements), but one needs, I think, a way to specify that you *really*
>> want a section of the selector to *only* apply to the scoped area.
>> Allowing :scope/:context would do wonders here, as well as make it
>> easy to define the stricter forms of scoped matching that Andrew likes
>> - as written earlier in the thread, the stricter forms would just
>> auto-prepend :scope/:context to the passed selector.
>>
>
> auto-prepended :scope/:context simply means that you work on isolated
> sub-tree.
> So you have your :root element resolved to the element establishing the
> scope.
> So that was the initial question: why to have artificial and contradictory
> :scope/:context
> if you already have :root element?

You're conflating different things here.

If you implement a strictly-scoped querySelector by auto-prepending,
you are *not* just working on an isolated sub-tree.  Your selector is
still applied to the full document, it just has an extra string in
front of it.  Specifically, the definition of :root doesn't change at
all - it still matches the document root.

In other words, writing strictlyScopedQuerySelector( 'div span' )
would be exactly equivalent to writing querySelector( ':scope div
span' ).  Writing strictlyScopedQuerySelector( ':root div span' )
would be exactly equivalent to writing querySelector( ':scope :root
div span' ), which is either completely invalid or an empty match (I'm
not sure just how strict CSS is in the placement of :root).  Either
way, it doesn't do anything for you.

The reason why you have *both* :scope and :root has been expressed
before.  querySelector and <style scoped> selector strings *still
match against the entire document*.  The definition of :root never
changes.  Strictly scoped variants would still want some way to talk
about the root of the *scoped section*, though, and this is what
:scope/:context would refer to.  :root points to document root,
:scope/:context points to scope root.  There are still good use cases
for selecting off of document root, and even for combining both :root
and :scope/:context in a single selector.

The only way that redefining :root to be the scope root would make
sense is if you prevented scoped selectors from matching against the
entire document.  That is, you'd have to treat scoped selectors as if
they really were operating on a document fragment.  It has already
been decided, though, that scoped selectors should instead match on
the entire document, but only apply to the elements within scope.
This is a much more flexible solution and, with the addition of a
:scope/:context pseudoclass, a strict superset of the
document-fragment solution that you endorse.

~TJ
Received on Monday, 14 July 2008 21:46:57 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Monday, 27 April 2009 13:55:10 GMT