W3C home > Mailing lists > Public > www-style@w3.org > February 2011

Re: CSS Variables Draft Proposal

From: Tab Atkins Jr. <jackalmage@gmail.com>
Date: Thu, 10 Feb 2011 12:44:02 -0800
Message-ID: <AANLkTi=fXBdumN8EOaHXhBrVeOqB77VAsnaeGa9FY5ai@mail.gmail.com>
To: "Linss, Peter" <peter.linss@hp.com>
Cc: www-style list <www-style@w3.org>
On Wed, Feb 9, 2011 at 6:56 PM, Linss, Peter <peter.linss@hp.com> wrote:
> On 2/9/11 5:22 PM, "Tab Atkins Jr." <jackalmage@gmail.com> wrote:
> "A token stream" is really dangerous (or exceptionally powerful, depending
> on your point of view). You're definitely going to have to tighten this
> up.

Yeah, "token" isn't the word I want here.  More like "component
value".  I've edited the language in the draft, but this needs some
thought to capture the right concept.

> Consider:
> @var $foo bar, baz / 100px     ;
> Does that simply get dropped into place macro style? Including the leading
> and trailing whitespace?

@var is not a character macro (shudder).  This gets parsed into three
component values and two separators, and gets substituted in as such.

> Do we really want that?
> How about:
> @var $foo url(;
> @var $bar );
> p { content: $foo http://example.com/yikes.gif $bar }

Oh jeezus no.  I don't know the precise details of url() parsing, but
either that is parsed into a single $foo variable containing
"url(;\n@var $bar )", or they're both invalid.  Either way works for

>>Using variables is very easy too - they can be used anywhere you could
>>use a component value:
> I can see use cases for having variables in selectors or as properties.
> But we probably don't want to go there.

I think variable selectors have use-cases, but not directly.  There
are some interesting patterns that they permit when you combine mixins
and nested selectors, neither of which I've brought to the group yet.

>>p {
>>  color: $main-color;
>>  background: url(foo) $main-color no-repeat;
>>  list-style-image: radial-gradient($main-color, $secondary-color);
> FWIW, I truly despise this syntax. Yes, it's used in a bunch of
> programming languages, that doesn't make it good.
> One technical argument against it is that you can't abut a variable
> against a trailing identifier or number (unless you add a "eat one
> trailing whitespace rule like for escapes). Although depending on how the
> "token stream" gets restricted this may not matter.

Yeah, that's not actually an issue, as it was never the intention that
a variable be able to do things like hold "px".  Variables should only
hold whole component values, or streams of them + separators.

>>Using a variable that hasn't been declared is a syntax error.  (It's
>>valid to use a variable that hasn't been declared *yet* - the
>>declaration may appear later in the stylesheet, or in another sheet
> Don't use the term "syntax error" here. I read this as "invalid and may be
> thrown away at parse time", which is clearly not your intent.
> Better to define referencing an undefined variable as having a 'null'
> value, or more likely a value of 'invalid' which is a special token
> meaning that it's there, but will always be invalid. You also need a way
> to "unset" a variable via script and/or set it to a null/invalid value.

You definitely understand my intent here.  I'm open to better ways to
express this.  I like the idea of an always-invalid special value.
I'll put that in the draft.

An interesting issue - how does an invalid variable get treated when
you ask to serialize the property?  I'm going to assume it's
serialized as itself, since the syntax for variable names is already
designed to always be invalid.  (Is this true?)

>>Variables and @import, etc.
>>Variables exist in the global scope.  @import'ing a stylesheet makes
>>any variables contained within it available to all other sheets.
>>Similarly, linking in a stylesheet makes any variables contained
>>within it available to all other sheets.
> A mention of alternate stylesheets as well as disabled stylesheets would
> be good here too. I presume the variables should be out of scope if the
> stylesheet isn't applied.

Yes, variables come out of active stylesheets only.  I've added a mention.

>>The latter two declarations form a dependency cycle, and so are
>>invalid.  A single variable named `$foo` is created, with the value
>>`red`.  If you then delete the third rule, the second is no longer
>>part of a cycle, so the `$bar` variable is valid and contains the
>>value `red` as well.
> Invalid at parse time or at run time? If variables are changed via script
> you should detect and deal with (or detect the absence of) loops after
> each change...

Runtime, I would think, since you can change the value of a variable
(and potentially introduce or remove loops) at runtime.

>>Deleting a map entry either deletes the current declaration producing
>>that value, or deletes all declarations defining that variable.  The
>>former is more symmetric with the underlying behavior of the "change"
>>action, but the latter is more symmetric with the *apparent* behavior,
>>as the complexity of multiple declarations is hidden away.
> There should also be a way to access all declarations, even if overridden.
> Insert, remove, reorder, etc. Or (probably better) you can't change this
> list, only the values of the variables in it. And if you do, you're really
> changing the @var object in whichever stylesheet it came from.

Yes, changing a var through the css.vars map is always just sugar for
changing the @var object in the underlying stylesheet.

What's the use-case for messing with shadowed variable declarations?
You can access them through stylesheet groveling, if it's absolutely

>>To add a new map entry, we first define `css.stylesheet`, which
>>implements the `StyleSheet` interface.  This stylesheet is treated as
>>an author-level sheet placed after all other author-level sheets.
>>Creating a new map entry creates a corresponding @var rule in this
>>stylesheet.  (Should this exist in `document.stylesheets`?  If so,
> As I think about it, adding and removing @var rules should probably only
> exist in the document.stylesheet interface.

I might agree with you about removing variables.  Adding variables,
though, is a useful ability that shouldn't require the excessive
effort of finding a stylesheet and adding a new @-rule.

>>To map a variable name to a key in the variables map, follow these steps:
>>1. Remove the $ prefix from the name.
>>2. Lowercase the remaining letters.
>>3. Uppercase any letters that immediately follow a hyphen.
>>4. Remove any hyphens.
>>Given this algorithm, a variable like `$main-color` will be accessed
>>as `css.vars.mainColor`.
> And if I had a variable named $mainColor ? You're effectively making them
> equivalent...

My intention was that variable names were case-insensitive, like
attribute names, but there's nothing about IDENTs that makes that
necessary.  Instead, I've just dropped the special rules.  If you have
an appropriately named variable, you can access it with vars.foo.  If
not, just use vars['foo-bar'].  The only special rule is that vars
don't have the $ prefix in the var map.

> And if the value of the variable is a list of values? (like for a
> shorthand)

I don't understand the context of the question.

On Wed, Feb 9, 2011 at 10:31 PM, Daniel Glazman
<daniel.glazman@disruptive-innovations.com> wrote:
> Le 10/02/11 02:22, Tab Atkins Jr. a écrit :
>> Requirements
>> ------------
> 5. All variable assignments and calls to variables should be modifiable
>   through an extension of the CSS Object Model so stylesheets using
>   variables can be loaded, modified and reserialized without loss.

Added, somewhat paraphrased.

> See:
>  @var $foo red;
>  @var $foo $bar;
>  @var $bar $foo;
> Two last rules dropped, you say $foo should default to red. But that
> will require preserving a stack of variable assignments since red is
> lost when |@var $foo $bar;| is parsed... That one becomes invalid
> only when the NEXT rule is parsed! Right after second rule, $foo
> is assigned through a deferred rule targeting the value of $bar.
> I think you have to clarify this section.

Indeed, that is the intention.  Browsers have to be able to fall back
to previous values anyway, for when a variable is deleted from a

If this is unacceptable, we can just say that in the above situation
$foo and $bar would both be guaranteed-invalid values (the same as if
they were undefined).

> In our (Hyatt and I) spec, variables were on a per-medium basis. That's
> not the case of your proposal. I see some pros and some cons. Not sure
> I like your choice. I think $foo should be allowed to have one value
> for screen and another one for print. Or one for a given media query
> and another one for another media query...

Hm?  My variables are indeed per-medium - it states in the "Variables
Availability and Scope" section (new name, but relevant text existed
previously) that @var rules nested in @media are only available if the
media query is true.

Right now, though, I guess the text only applies to vars specifically
in @media, not ones in media-specific stylesheets.  I've altered the
text to be more general here.

Received on Thursday, 10 February 2011 20:44:57 UTC

This archive was generated by hypermail 2.3.1 : Monday, 2 May 2016 14:38:43 UTC