[css-variables] Putting it all toegether (syntax)

CSS Variable's syntax has been a very hot topic recently, with no strong 
majority so far. For the past few days, I really tried to make own all the 
remarks made by the people I was able to discuss with, and to see how all 
those (sometimes apparently opposed) point of views could be merged in a 
single, coherent proposal; I think I kinda succeeded.

However, before I jump to anything concrete, I would like to give some 
context about the main beliefs I’ve been conciliating in the process, and 
the reasons I chose them.



1.    $foo is a popular replacement-initiator token

While few languages, to the notable exception of PHP, are actually using the 
dollar symbol as part of their variable names, it seems that many 
replacement-based systems are using $ as a magic token introducing a 
(string) replacement. Samples of this trend include PHP, BASH, REGEXP, XSLT 
and POWERSHELL.

Based on the opinions expressed on this list and on Twitter, it seems that 
going against that movement is a difficultly sustainable position. Catalysts 
include habits, consistency with existing programming languages and no 
breaking change required for the value tokenizer (to the contrary of a 'just 
use the variable name' approach).



2.    People’s expectations of variables won’t meet CSS implementation

CSS variables exhibit a behavior fairly distant from any variable 
implementation to date. Many invariants of traditional variables are not 
going to be met by CSS variables. Avoiding confusion has thus to be a key 
criterion in our syntax choice.

As people have divergent experiences and knowledge, a good choice should as 
much as possible rely on the already-existing understanding of the CSS 
language. Besides being defined the same way as CSS properties, CSS 
variables are going to behave in a very similar way (regarding inheritance, 
cascading, scope, and value tokenization). In fact, in the current working 
draft, they are even defined as traditional CSS properties. This led me in 
the past go as far as calling them “user-defined properties”. I think this 
is something to preserve.



3.    Learning from HTML: An user-defined property is still a property

Just like the HTML data attributes are specification-defined user-reserved 
attributes having no effect on the document’s rendering and behavior (unlike 
other HTML attributes), CSS variables aren’t going to have any impact on the 
page (unlike other CSS properties) unless some user code defines how to 
perform the mapping between those user-defined properties and the 
framework-understandable ones.

In CSS, this mapping process is likely to happen in two ways: using token 
replacement in other CSS properties (previously var()), and using 
client-side scripting (via DOM/CSSOM). In the HTML case, mapping tools are 
quite similar: CSS' attr() and scripting are likely to be used.



4.    Often, prequels are important to understand a story

The first recognized use of variable in CSS is often seen as the 
‘currentColor’ keyword. This keyword has a very special behavior in the 
sense it computes to the value of the color property. When creating a 
dependency circle (color: currentColor), the declaration is treated just 
like an invalid-at-runtime CSS variable would, and ‘color’ returns to its 
default state (inherit).

This example is interesting for two reasons: because it shows that, quickly, 
‘variables’ have shown to be necessary for representing the complexity of 
page layouts and because it seems that even ‘native’ CSS properties (I call 
them framework-provided) can be a reference target (more on that later; I 
just want you to keep this in mind for the moment).

Another variable-like use-cases include the ‘em’ unit (which is nothing more 
than the (computed) value of the ‘font-size’ property) and the newly created 
‘align-items’ (which can be understood as a default value for the otherwise 
not-inherited ‘align’ property).



5.    Why we don’t want { $foo: bar }

As noted by some users, this syntax is confusing; firstly because authors 
expect intuitively to be able to use preprocessor variables anywhere, 
including in selectors and to shorten property names. This means that “$foo: 
bar” can easily be confused as “the property name contained by the foo 
variable should be set to bar” instead of “the foo variable should be set to 
bar”.

Secondly, this is breaking the core CSS grammar which has been referenced as 
non-updatable by this working group several times. Reasons include 
incompatibility with tools and browsers. “html { $color: red; }” is for 
example understood as “html { color: red; }” by IE6 and IE7. Compatibility 
with existing tools is clearly something we should take care.

Last but not least, this is hiding the property-like nature of CSS 
variables, which severely impairs the clarity and discoverability of the 
feature.



6.    Why we need a prefix

However, if we don’t use the $ prefix, we have to restrict the names authors 
can give to their user-defined properties. The reason is pretty clear: a CSS 
variable should never collide with a future framework-provided property. If 
variable names are constrained by a prefix, this becomes a no-brainer: 
future properties won't use that prefix.

Based on my reflection, I initially coined the “x-” prefix (whic is a nice 
and short prefix for user-defined things) but Sylvain noted it’s being 
deprecated in the HTTP protocol. My current preference goes to a 'my-' 
prefix; however, a more consensual choice like “data-” is probably seen as 
more acceptable by the WG members, I don't know.

[[Disgress: Actually, it’s to be noted that "data-" was the used prefix 
before the current draft and made consensus at the time in the CSS WG. 
However, the data() function led many to think this would be confused with 
HTML’s data attributes. This function being gone, I think we can remove that 
fear from our list and benefit from the name semantics. In fact, I think 
that the similarity of working between HTML’ data attributes and CSS 
variables can gain to be outlined.]]



7.    Variables should be consistent in name

Last but not least, many stated on this list that they din't like the fact a 
variable "changed" of name between the time it's been set and the time it's 
retreived. Because it makes things much clearer when the name is contant, I 
wanted to keep it so in my proposal.



8.    Sum it all up

Here’s finally a sample file based on my syntax proposal:

    :root {
        my-link-color: red;
    }

    header {
        my-link-color: white;
    }

    a {
        color: $my-link-color;
    }

I think it takes in consideration all of the seven preceeding points, and is 
a balanced solution.



9.    Things I would like to highlight

Here are important things I would like you to note about the proposal:

-    The $ is not part of the property name: this is a replacement indicator 
token.
This means that it can be reused for any future replacement behavior that 
may benefit from it: this is very future-proof.

-    Variables are still properties like any other.
In a future revision of the spec, we may allow things like $color (a value 
semantically equivalent to currentColor). There’s no reason a property could 
not reference the specified value of another property as long as no 
dependency circle is created. And we now have a solid resolution to apply in 
case such a dependency circle happens in practice.



10.    Thoughts?

Please feel free to comment this proposal; I’m eager to see what you all 
think of it.


Thank you all for reading a so long mail up to the end!
François 

Received on Monday, 4 June 2012 18:07:01 UTC