CSS Variables land in WebKit
trac.webkit.org
trac.webkit.org
Unlike other technologies like canvas or AJAX where we've been able to create polyfills for older browsers, authors will now have to make an explicit decision between either using CSS variables or supporting all browsers.
That cascade depends on the structure of the document, not just the CSS. For instance, consider the following (contrived) example:
:root { var-accent: black; }
.someclass > :first-child { var-accent: blue; }
.otherclass { background-color: var(accent); }
.anotherclass :first-letter { color: var(accent); }
The value of var(accent) for any element depends on whether the ancestors of that element include the first child of an element with class="someclass". For a preprocessor to duplicate that effect on the server side, it would need to construct all possible combinations of the selectors for the variables and the selectors depending on those variables: .otherclass { background-color: black; }
.anotherclass :first-letter { color: black; }
.someclass > :first-child .otherclass { background-color: blue; }
.someclass > :first-child .anotherclass :first-letter { color: blue; }
Now consider that with a dozen variables and a hundred variable-dependent rules.> On the other hand, if you can really edit variable values with Javascript then that would be client-side only, although I haven't seen anything that says you _can_ do that - for all we know Javascript may only allow getting/setting of the evaluated value, not the variable expression itself.
The CSS Variables spec talks about dynamic variable updates via scripting.
div { var-color: red; }
p { var-color: blue; }
section a { color: var(color); }
It is not possible to generate a non-variable version of the CSS without either knowing the structure of the DOM or generating every permutation of selectors (you can imagine how unwieldy this could get). Even if you manage to do this you're changing the specificity of the rules.More directly, though, things that can be done by a preprocessor are, by their very nature, less attractive for us to work on. Syntax improvements are nice, and can justify their existence in the core language, but more important to us in the CSSWG is adding functionality that can't be achieved any other way, or not without a lot of painful hacking.
I'd rather let a thousand flowers bloom on the syntax side while I spend my limited time adding new features.
As we already have servers, and we even already have preprocessors, it provides no benefit to having it in the client to just bake that in. The result isn't even much less efficient: the variable is not going to be that much smaller than the value itself pasted in.
When you combine the want to support popular older browsers, the fact that not everyone will implement it at all, and the assured compatibility issues between implementations, we will just be running the preprocessor anyway and using it for every browser (again: as there is almost no benefit to using the native implementation). By the time we aren't, there will be some other feature we really want the preprocessor for.
However, being able to have variables in media queries does provide drastically different capabilities as a compile target for our preprocessors. To simulate having variables in media queries requires preprocessors to fork entire rules with each of the different possible media query expansions for the variable. This is an actual (albeit not gigantic) benefit that will allow users to download smaller CSS files if the server detects they can handle it.
Therefore, I would look at this more like a CPU that added a new instruction that cannot be implemented as a macro-expansion in an assembler, but for compilers of high-level languages that are capable of detecting support for it, allows much faster or smaller execution when available.
Using Less has been one of the most profound upgrades in my use of programming techniques in quite a while. Hopefully browsers will eventually support even more Less-like features.
1. constants (mostly for colors and a few sizes)
2. mixins/functions/macros for not-completely-standard properties (e.g. gradients, shadows), makes it easier to not forget a prefixed version, easier to update the definition when needed and much, much easier to read
3. nesting and continuations, especially for styling various states of e.g. a link (having to copy/paste a given selector 4 times and change the pseudo-class is no fun).
Still requires some care though, overusing e.g. nesting can mean you find yourself with fucked up huge selectors in the final file.
Don't look at them, use then, and you'll see.
>I don't want a turing-complete language in my css. Simple variable expansion will suffice--basically just syntactic sugar.
And they are mostly that --simple variable expansion. But arithmetic is also handy, e.g
.sidebar { width: @page_width - @content_width }
That said, they are not turing-complete as far as I know.
>I don't want yet another game of "find the definition" buried under a hierarchy of indirection.
You never get that. You only have to look at the LESS or SASS file, never the generated CSS.
And you can mentally map what you see in the browser's CSS inspector with the relevant LESS/SASS rule trivially.
It's nothing like Coffeescript in this regard, where you (sometimes) have to hunt to see the original error.
They do look nice but currently I still prefer not to blur the edges of what is or isn't CSS.
Also, this is a pretty high-level addition. I wouldn't be surprised if someone came up with a polyfill for this soon.
Possibly some sort of solution where the browser receives SASS/LESS files and compiles them into CSS on the fly?
:root {
var-header-color: #06c;
}
h1 { background-color: var(header-color); }
looks slightly hacky, but better than nothing at all I suppose...But seriously, this is extremely consistant with other css directives. Yes, I'm still going to just use less / stylus / whatever, but browser based vars mean some interesting possibilities sans js.
edit: I think I'll stick to PHP variables in my CSS for now:
<?=$color1?>I understand the danger of introducing PHP to CSS though. I won't be making database calls or anything like that from a .css file.
This proposal by the W3C is definitely not-even-half-baked.
:root { $header-color: #06c; } h1 { background-color: $header-color; }
(Note that the spec's use of the :root pseudo is just to generically declare "global" variables that should apply to the whole page. If you're just using HTML, feel free to use "html" or "body" as the selector instead.)
I'm guessing the justification for the existence of the awkward var(varname) version is so that you can also have the parent-var(varname) notation.
I do think it's interesting how variables are scoped to dom nodes. Is there any reason it cannot be optional though, so if you omit it, it defaults to global?
$header-color: #06c; h1 { background-color: $header-color; }
I'm guessing the argument against, is that this requires too much of a change to CSS parsers, as it doesn't follow the standard form of <selector> { <properties> }. If that's really the reason it seems a bit of a shame though :/
:root{ def-primarycolor: blue; }
.x{ background-color: $primarycolor; }
Much of the confusion I think is in the fact that we are referring to two dramatically different things by the same word "variables". In CSS terms it is more helpful (IMO) to think of them more like "user defined properties" which work exactly like every other property in CSS.
This example shows a variable property safely using a variable:
:root {
var-main-color: #c06;
var-accent-background: linear-gradient(to top, var(main-color), white);
}
The ‘var-accent-background’ property will automatically
update when the ‘var-main-color’ property is changed.
edit: clarified the wording of this comment to remove ambiguity (not a question).EDIT: parent originally asked about the difference between this and SASS/LESS.
> EDIT: parent originally asked about the difference between this and SASS/LESS.
Safari on the other hand...probably a year or so. Possibly what comes after mountain lion. They won't add it in until it is fairly stable.
Putting color codes in one variable will help a lot.
Seriously the boorish comments about "no support yet" are like listening to fat client advocates in the 90s.
Cross browser support is not always necessary.
One thing that will help (once it's supported, heh) is the @supports rule http://dev.w3.org/csswg/css3-conditional/#at-supports . (Actually, it'll help even before it's supported, since you can put the "down-level" version outside the rule and then reverse the properties and do the new stuff inside the rule. The inner bits will be completely ignored in old browsers.)