Better Variables through Custom Properties

This is a continuation of Roland Steiner's thread from
<http://lists.w3.org/Archives/Public/www-style/2011Oct/0212.html>,
more closely targeted at Variables specifically.

Currently, the Variables draft that I'm working on defines variables
via a top-level @var rule, which defines the variable globally.  I'm
deferring the problem of scoping/namespacing variables until later.

Roland brought up another idea which I believe is a strict improvement
over mine, in several ways: using custom properties to define
"variables" that then work with the normal CSS cascade.

Let's look at an example.  Here's a sample variable declaration and
use using the current grammar in the spec:

@var $main-color #06c;
@var $accent-color #006;
h1 {
  color: $main-color;
  border-left: thick solid $accent-color;
}

Here's the same example, using a slight variant on Roland's suggested grammar:

:root {
  data-main-color: #06c;
  data-accent-color: #006;
}
h1 {
  color: data(main-color);
  border-left: thick solid data(accent-color);
}

In this simple case, two custom properties are set on the root
element.  They inherit down to the h1, where they are referenced with
the data() function.  Here I'm assuming that properties prefixed with
"data-" are "custom properties", which are valid but defined to be
meaningless, similar to the data-* attributes in HTML.

This is a pretty trivial example that doesn't show much benefit over
the current grammar.  However's Roland's idea has several benefits:

1. Variables can be scoped to particular subsets of the element tree.
Roland talked about this being useful for components (a la the
Component Model, currently being discussed in WHATWG/WebAppsWG), but
it's useful more generally for ad hoc "components" as well, such as
those espoused by the OOCSS discipline and similar.

2. Scoping gives us a useful form of "namespacing" as well.  If you
set a variable on the root of your component (Component Model or
ad-hoc), your variable won't show up for elements outside of the
component.  As well, if the same variable name was used outside your
component, it won't affect *your* styles either.  (This isn't perfect,
as "donut"-style components that contain arbitrary content will still
see your component's value, and not the global value.)

3. People have previously asked for the ability to use CSS to assign
and pass around values purely for JS, because the cascade is a pretty
useful tool.  Those use-cases get addressed for free here.

4. The CSSOM for this is simpler, since it's just a normal property
and can be accessed or modified through the existing .style interface.

5. Variables can be set directly on an element through the @style attribute.

6. Tools like Chrome's Web Inspector can show the value of variables
in a simpler way, since they're normal properties.

As far as I can tell, there's not a single downside to using Roland's
suggestion instead of the current suggested grammar, and a lot of
upsides.  What do others think?

~TJ

Received on Monday, 24 October 2011 23:40:39 UTC