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

Re: Selector Sugar

From: Tab Atkins Jr. <jackalmage@gmail.com>
Date: Thu, 9 Oct 2008 12:25:07 -0500
Message-ID: <dd0fbad0810091025q710715d4w49984acb8413c453@mail.gmail.com>
To: "Brad Kemper" <brkemper.comcast@gmail.com>, "François REMY" <fremycompany_pub@yahoo.fr>
Cc: "W3C Style List" <www-style@w3.org>
On Thu, Oct 9, 2008 at 12:04 PM, François REMY <fremycompany_pub@yahoo.fr>wrote:

>  Another possibility I think great for both your queries is :
>     #top-courses, #additionnal-courses {
>         @rule ul {
>             display: inline-block;
>         };
>         @rule h3 {
>             color: darkblue;
>          };
>         border: none;
>     }

I'd have to look, but I think that would mess with the parsing rules as
currently written.  I'd rather have an equivalent syntax that meshes more
naturally with existing content, like what you have below:

> An equivalent, with your proposals will be :
>     @scoped ( :any(#top-courses, #additionnal-courses) ) {
>         :root {
>             border: none;
>         }
>         ul {
>             display: inline-block;
>         }
>         h3 {
>             color: darblue;
>         }
>     }

 Looks like I didn't mention it, but my intention is for @scoped to accept
arbitrary selectors, not just simple selectors.  So (assuming :any() was
implemented) there would be nothing wrong with the above.  After all, being
able to avoid typing a single simple selector is a fairly minor benefit
(though I have a use-case in my current work that this would aid me with
quite a bit, as I explained in the original email), but sometimes one runs
into a situation where a fairly complex selector would be repeated over and
over again.

On Thu, Oct 9, 2008 at 12:10 PM, Brad Kemper <brkemper.comcast@gmail.com>wrote:

> On Oct 9, 2008, at 8:53 AM, Tab Atkins Jr. wrote:
>  I want to talk about two issues of syntactic sugar that I believe would be
>> very useful to us authors.  Neither actually change anything in the way CSS
>> works or produce new burden on implementors - both are merely sugary
>> conventions that would allow us authors to shorten some thing we currently
>> write out manually.  I know I've seen both of these suggested before in
>> various syntaxes; I just want to bring them together in what I think is an
>> appropriate syntax for each, so as to provoke new discussion in a thread
>> specially dedicated to them.
>> (1) Scoped selectors within a stylesheet.
>> Good, semantic authoring often entails a relative paucity of named hooks
>> into the document (in the form of ids and classes), with most of the actual
>> CSS targetting being done through relatively complex selectors descending
>> from some named hook.  Frex, a navigation menu may *only* id its enclosing
>> div, and target all of its styling purely by structurally descending from
>> that #id.  The issue with this is that you have large swathes of selectors
>> that share a common prefix, which must be repeated on every single rule.
>>  This can be simplified by creating a block in which every rule is assumed
>> to be scoped to an area.  My first thought is an @ rule, something like the
>> following:
>> @scoped( #nav-menu ) {
>> h1 {
>> //This is equivalent to the selector "#nav-menu h1",
>> //and so won't target <h1>s across the rest of the page.
>> ...
>> }
>> ul {
>> ...
>> }
>> more rules...
>> } //end of scope
>> I would find benefit from this immediately, as all of the sites I operate
>> on utilize the same basic mechanisms.  They consist of a template which is
>> styled by a dedicated sheet, and then has content piped in from a database
>> which also pulls in the page-specific styling.  The page-specific styling
>> should *never* affect the outside template, and current I accomplish that by
>> iding the content container and just prefixing *every* rule in *every* page
>> with that id.  I've purposely made the id extremely short (it's just "bc"
>> for "body content") so it's not overly burdensome to type, but that's still
>> a lot of meaningless typing that could easily be taken out with the addition
>> of a single scoping line.
>> Even past the convenience factor, there's a safety factor.  I hand-craft
>> the styles across my company's site, because nobody else in the company
>> really has appropriate skill to do so, but even I sometimes forget to use
>> the #bc prefix on a rule.  The damage is usually immediatley obvious, as I
>> suddenly give every header some enormous background or something, but it's
>> also unnecessary.  Forcing other people who are relative newbs at styling to
>> remember to arbitrarily prefix all their rules with #bc as well is just
>> frustration waiting to happen.  I could, of course, build a CSS parser that
>> alters the rules myself, but why reinvent the wheel every time when it can
>> be simply fixed in the language itself?
>> Ignoring any possible optimizations, this is a simple matter of the parser
>> doing a simple textual concatenation before handing the selectors to the
>> matcher.  This construct should also be nestable, for obvious reasons.
>> (2) Multi-matching selector
>> This was suggested just recently and also came up in the jQuery thread a
>> few moments ago, and I would also benefit greatly from this.  The idea is
>> that, rather commonly, you have to apply the same style across several
>> elements with different classes or whatnot.  This isn't burdensome when
>> you're writing a single group of selectors, but when you have a large chunk
>> of selectors that all have to be generalized you quickly run into a
>> nightmare of typing.  For example, in something I'm typing *right now*, I
>> have a lot of selectors which look like this:
>> #top-courses div.chapters h3, #additional-courses div.chapters h3 { ... }
>> #top-courses and #additional-courses are two (of several) sections which
>> all share a similar structure, but they have some special styling needs that
>> set them apart from the others.  Right now I need to duplicate every
>> selector I make, which adds up to quite a few in this particular example.
>>  With a multi-matching combinator I could avoid the duplication.  It would
>> look something like this:
>> :any( #top-courses, #additional-courses ) div.chapters h3 { ... }
>> ...with the :any pseudoclass being simple sugar that stands for any of the
>> selectors contained within it.  :any should accept arbitrary selectors,
>> separated by commas, since it's basically just performing a simple textual
>> substitution in the selector.  Though there are surely optimizations that
>> can be performed, in the simple case all that's needed is for the parser to
>> transform away the :any and produce two separate selectors to be handed to
>> the matcher.
>> It is certainly possible for authors to get the same functionality by
>> going into the code and adding additional classes.  That's why this is
>> syntax sugar, not new functionality.  ^_^  Doing such means altering the
>> document when you just want to save some typing in the stylesheet, and
>> possibly leaks presentational classes into the document (some times you can
>> certainly come up with a semantic reason for the class, of course).  As
>> well, style authors don't always have access to the document source,
>> particularly in cases like writing up Stylish-like user-stylesheets.
>> Thoughts on these proposals?  Any ideas for other simple bits of sugar
>> that would help us authors out?  I'm looking specifically for ones that
>> don't add new functionality, but rather only shorten the amount of typing we
>> have to do when writing styles.
>> ~TJ
> I agree that those would be valuable. There was some discussion back in
> February about "selector variables" (from Jens Meiert) and "selector
> constants" (from me), that were also syntactic sugar for selectors. They
> solved some of the same problems, but your ideas above do even better for
> certain cases. Your #1 above is actually pretty similar to how Alan Gresley
> misunderstood my proposal, which has value in its own right:
> http://lists.w3.org/Archives/Public/www-style/2008Feb/0145.html

Cool.  I wasn't following the list back then, so thank you for pointing it
out.  Selector constants solve a similar problem to the @scoped rule, but
there they let you dump a complex selector anywhere within a selector.
@scoped misses out on this, but results in even *less* typing (using a
selector constant for a common prefix still means typing a prefix over and
over, even though it's shorter).  You're right that they both have
interesting value, and I can see a definite purpose for constants that would
make writing chunks of selectors more maintainable and easier to understand.

> I wonder if it might even be possible to leave out the @scoped, and just
> have it like this to do the same thing:
> #nav-menu {
> h1 {
>        //This is equivalent to the selector "#nav-menu h1",
>        //and so won't target <h1>s across the rest of the page.
>        ...
>        }
> ul {
>        ...
>        }
>        more rules...
> } //end of scope
> That would mean that the parser would have to not only look for property
> names inside the curly braces, but also for other selectors. And that way,
> not only is there less to write, but you could include styling for the base
> selector, like this:
> #nav-menu {
>        border: 2px solid red;
>        background-color: blue;
>        h1 {
>        //This is equivalent to the selector "#nav-menu h1",
>        //and so won't target <h1>s across the rest of the page.
>        ...
>        }
>        ul {
>        ...
>        }
>        more rules...
> } //end of scope

It would be slightly less writing, but now we're talking about the
difference of a couple characters, compared to the linear savings of the
proposal itself.  I don't see any particular reason to need this
simplification, but I don't think I'd be against it either.  I just suspect
it would be more work for implementors than adding in a new at-rule.

Styling the base selector could also be accomplished in one of two ways.
Either :root can have its meaning changed within the context of a @scoped
rule to refer to the scoping element (Francois implicitly used this
approach), or we can just go the brain-dead simple route of stating the base
selector by itself.  Frex:

#nav-menu {
  ... //for the nav-menu itself
@scoped ( #nav-menu ) {
  ... //for the children of nav-menu

I don't have a preference either way, but I have absolutely nothing against
the simple method here.

Received on Thursday, 9 October 2008 17:25:49 GMT

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