Regular variables
Variables in Active CSS are different to CSS variables. CSS variables are supported in ACSS, but those are for adjusting style properties in stylesheets.
Variables in ACSS start with a dollar, and can contain any common value, including elements.
They operate similar to the SCSS syntax, but can accept any JavaScript expression:
$something: "Hi there";
$somethingElse: "Hi there".replace(/there/, "Dave");
Outside of double-quotes, like in an @if statement, they are used like this:
@if ($something == "Hi there") {
render: "Hello";
}
Inside of double-quotes, like when you need to render something, they are used like this, in curly braces:
$name: "Bob";
render: "Hi there {$name}";
If you need to use variables in an expression when you render, you can use the JavaScript expression wrapper {= =} inside quotes (and actually in most places in ACSS), and include whatever JavaScript expression that you need:
$dangerousHTML: "<script>alert('hack attack')</script>";
render: "This will display as safe text: {= escapeHTML($dangerousHTML) + ". Nice try!" =}";
Ref: escapeHTML()
When rendering variables in component html blocks, put them in curlies like this:
@component hello-world {
html {
<p>My name is {$name}.</p>
}
}
There are a lot more examples on how to use variables in different scenarios on the var command documentation page. The var command used to be the way to use variables, but since the dollar syntax was introduced, it isn't used so much. You can still use it to set non-dollar prefixed ACSS variables, but non-dollar variables are now an unsupported variable type because the syntax can get confusing. You do still need the var command when setting window variables, so the var command has not been deprecated.
Variable scopes
There are 3 types of variable scopes used in Active CSS.
1. The document scope. All Active CSS variables are automatically in the document scope, unless they are inside a private component area.
2. The private component scope. This refers to Active CSS variables only. Components can be placed inside other components - they are quite flexible - they are not bound to each other. Each component is its own thing, but can be used in other components as needed. Each component can have its own scope, but it also inherits the scope of its parent unless it is a strictly private component. So if the outer component is a strictly private component, but the inner component has no scope at all, then the variables used in the two inner components are shared in both component scopes, but are not available in the scope outside of the outer component (because it is strictly private). Variables follow the "component-in-component" scoping rules. See the components section of the docs to study up on components.
3. Private JavaScript function scope when running JavaScript blocks (like with the run command). All JavaScript functions have a naturally self-contained scope.
4. The window scope.
Active CSS variables are not easily available in JavaScript from the window scope. They are designed to be internal to Active CSS, although you can send them to external functions. You can also get and set window variables from ACSS config.
To set a window variable, you can use the old ACSS "var" command, which was a former ACSS command for declaring variables. There is no other syntax for assigning window variables at this time.
var: window.something "Hi there";
render: "Greeting: {window.something}";
More on variables
You can use the same variable name in different scopes and they won't clash.
You can set up variables for strings, booleans (true/false), numbers, arrays, elements or JavaScript objects, like you would in JavaScript. The syntax for writing a value is the same as JavaScript.
For example:
$player: "X";
This sets up a variable called "player", and gives it a value of "X".
It is the equivalent of this in JavaScript:
var player = "X";
Why not use the existing CSS variable syntax? It wouldn't work alongside JavaScript. Mainly because the "--" used as a prefix for CSS variables is the decrement operator in JavaScript, so it is an incompatible syntax if used raw. Of equal importance, having to use the CSS var(--varname) syntax for logic purposes in JavaScript is a lot to type each time you want to use a variable. So we get rid of the "--" and get rid of the "var()" and just add a "$", and when using a variable in a CSS command we put it inside curly braces. For maximum flexibility, the dollar-prefixed value was chosen. It is a valid variable syntax in native JavaScript and familiar to those who have used PHP and SCSS, which have been powering the internet for decades.
It's actually quite handy that CSS variables and ACSS variables are separate - behind the scenes it keeps the distinction between the rendering engine and the event engine, which means the two variable types don't ever clash. Also, seeing as CSS variables are supported in ACSS syntax, it is good to be able to spot the difference between them easily when both are present in ACSS config.
Reactive variables
In ACSS, a reactive variable is a variable that you render once, and thereafter whenever the variable changes, the rendered variable updates.
This is a targeted update. Surrounding code is not affected.
To render a reactive variable, place it in double-curly braces, like this:
render: "The player is: {{$player}}";
You can also data-bind (make reactive) items in arrays and also object properties:
render: "{{$myObject.mySubObject.ref}} {{$myArray[0]}}";
This means that whenever the variable changes in memory, it will also change wherever you have data-bound it on the page. There are examples of this in the examples section of this site. Only ACSS variables can be made reactive - variables declared outside of ACSS cannot be made reactive inside ACSS.
Using an ACSS variable inside a JavaScript block
To access an ACSS inside a JavaScript block, such as inside the "run" command, you need to declare it as available in the block first, by using a special ACSS JavaScript command, "vars". The variable must have been previously declared before being used in the run command.
For example, you are on a broccoli diet, and want to remind yourself of this every time you click on a button:
body:init {
$food: [];
$nowFood: "";
run: {=
vars $food, $nowFood;
$food = ['broccoli', 'cheese', 'tofu', 'chicken'];
$nowFood = $food[0];
=};
}
button:click {
render-after-end: "I like {$food[1]} and {$food[2]}, and also {$food[3]}, but what I am having today is {$nowFood}.";
}
The same thing without the run command:
body:init {
$food: ['broccoli', 'cheese', 'tofu', 'chicken'];
$nowFood: $food[0];
}
button:click {
render-after-end: "I like {$food[1]} and {$food[2]}, and also {$food[3]}, but what I am having today is {$nowFood}.";
}