-
Notifications
You must be signed in to change notification settings - Fork 1
Cascading Style Sheets Script Specification
Second draft, 03-03-17
This page defines all aspects of the Cascading Style Sheets Script language, abbreviated to CSSS. CSSS builds upon the CSS syntax with new parts to allow server-side generating of HTML, complete with styling.
Normally a script is executed from the top to the bottom, however, control flow statements can alter the flow of execution of the script. In CSSS, all control flow statements start with an @
symbol.
The if
, elif
and else
blocks can also be used within elements, see below.
if
statements only execute the code contained in their block if the expression within their parentheses evaluates to true. Their syntax is as follows:
@if (expression) {
/* Some code */
}
The expression used has to return a boolean, but can otherwise be anything. For example:
@if (8 < 7) {
/* Code entered here never gets run */
}
In this case, the code within the if
block is not executed, as 8 < 7
results into false.
elif
statement has to be declared directly after an if
(or other elif
) statement's code block has closed. Very similar to an if
statement, it only executes the other code in its block when the expression within its parentheses evaluates to true, but with an added requirement: All previous if
or elif
statement's expression must have evaluated to false.
@if (false) {
/* Code that is never run */
}
@elif (true) {
/* Code that is run */
}
The else
statement's block of code is run when all the previous if
(or elif
) statements did not execute. Therefore it has to be directly below a code block of either one. else
should be the last statement in an if
-elif
-else
chain and can not be followed by an elif
.
@if (false) {
/* Code that is never run */
}
@else {
/* Code that will run */
}
A while
statement is the only way in CSSS to loop code. While the expression within its parentheses evaluates to true, the code in the code block will be run over and over again. while
statements look quite similar to an if
statement:
@while (true) {
/* Code that will run forever, as the expression will always be true */
}
Variables allow the script to store and retrieve information while running. All variable names should start with --
(2 dashes) followed by alphanumeric characters or dashes, matching [a-zA-Z0-9-]
. A valid name could be: --var-name
Variables do not need to be declared in any way before being written to, they are always ready to go. Keep in mind that this isn't true for reading them. All writing statements should be closed with a semicolon.
Writing a number or CSS unit can be written directly like a CSS property.
--var-name: 1px;
Strings need to be contained in either double quotes ("content"
) or single quotes ('content'
).
--var-name: "string contents";
An array can be filled with any value (number, array, boolean, CSS unit or string) of any length. It has a syntax very similar to javascript. The values are separated by commas and the entire array is contained within square brackets ([]
).
--var-name: [1, "string", 10vh];
Writing a value to a specific location in the array is also exactly the same as it is in javascript. The array index starts at 0, so accessing the first value will be done as such:
--var-name[0]: "new string";
To append a value to the end of the array, simply write to the -1
index of the array.
--var-name[-1]: "appended string";
To read from a variable simply mention its name anywhere you would normally enter a static value:
--var-name
Reading from an array is also quite simple if you know how to write to an array:
--var-name[1]
In CSSS, all mathematical operations have to be done within a calc()
block, similar to CSS. The exception to this rule are the parentheses of some control flow statements, which also act as calc()
blocks.
Most of the syntax here is taken directly from javascript, so anyone familiar with web technologies can learn them quickly.
Arithmetic operations take 2 values and perform an operation, after which only 1 value remains. Values are always read from the left to the right, regardless of operator type. The 4 types of arithmetic operations supported are addition, subtraction, multiplication, division, modulo and exponentiation.
Operator | Type |
---|---|
+ | Addition |
- | Subtraction |
* | Multiplication |
/ | Division |
% | Modulo |
^ | Exponentiation |
Note, however, that strings only support the addition operator. When adding any non-string value to a string the value will be converted to a string and appended to the string.
An example of an arithmetic operation would be:
calc(40px + 60px / 2)
Of which the result would be 50px
. Combining values with different units is not a problem, the calc()
block will be passed to the output CSS for the browser to resolve.
Comparison operators take 2 values and perform an operation, after which only a single boolean remains. There should only be 1 comparison operator per block, but you can start a new parenthesis block if needed. So for example, (false == 8 > 7)
would throw an error, while (false == (8 > 7))
will execute normally.
Operator | Type |
---|---|
== | Equal to |
!= | Not equal to |
> | Greater than |
< | Less than |
>= | Greater than or equal to |
<= | Less than or equal to |
The equal to (==
) and not equal to (!=
) comparison operators will compare any type of value, while all other operators only accept numbers.
Remember that the results of a logical operation should never be passed to a property, as they always return a boolean and no CSS property accepts booleans at this time. An example of using a logical operator could be:
calc(30vh >= 70vw)
Of which the result would be false
. Note how only the numbers are compared in this case, the units do no matter.
Logical operators take 2 booleans and return a single boolean. There can be multiple logical operators within a single calc()
block if needed.
Operator | Type |
---|---|
&& | And |
|| | Or |
! | Not |
Just like logical operations, the results of a logical operation should never be passed to a property, as they always return a boolean. An example of using a logical operator could be:
calc(!true || false)
Which would return false
.
Elements allow scripts to add HTML elements to the output HTML. They consist of a CSS selector with a block of CSS properties.
New elements are always added after the last element in the body tag. All other HTML, like the doctype and head element, will be added automatically. The syntax is as follows:
selector {
property: value;
}
The selector defines the type of element that will be added to the HTML. The selector always starts with the tag name, but all other parts can be added in any order.
This is the name of the HTML5 tag and should start with a letter ([a-zA-Z]
), optionally followed by alphanumeric characters ([a-zA-Z0-9]
). An example of this would be:
div
Element IDs are added to the HTML element by adding a hashtag followed by alphanumeric characters, dashes or underscores ([a-zA-Z0-9_-]
). An example of an ID added to a div
tag selector would be:
div#id1
IDs should be unique for the entire document, and should therefore never be used in a loop.
Element classes are added to the HTML element by adding a dot (.
) followed by alphanumeric characters, dashes or underscores ([a-zA-Z0-9_-]
). An example of an ID added to a div
tag selector would be:
div.class1
To add another class to the element, simply add another dot:
div.class1.class2
Adding attributes is a little more complicated than the others, they start with an opening bracket ([
) followed by the attribute name. The name can contain alphanumeric characters, dashes or underscores ([a-zA-Z0-9_-]
). After the name should be a single equality sign (=
), followed by the attribute value as a string, or a calc()
block that returns a string. Finally, the whole thing ends with a closing bracket (]
).
In short the syntax comes down to [name="value"]
. For example:
div[data-size="3"]
Elements can have multiple attributes, to add another one simply repeat the block:
div[data-size="3"][data-name="kees"]
There is no requirement to start a custom attribute with the data-
prefix, but it is encouraged.
An element property sets the CSS property for the HTML element. This should start with the property name, which should only contain letters and dashes ([a-zA-Z-]
), followed by a colon (:
). After that follows the property value, which can be either a number, string, value (such as a color) or calc()
block. The property terminates at the final semicolon (;
).
In short, the syntax comes down to property: value;
. For example:
border-width: 2px;
The content
property works differently in CSSS, as it can be added to any element. Use it to write plain text to the document.
Elements can be nested within other elements, which will make it their children in the DOM. Simply add them somewhere within the block of the parent element.
For example, take the following example:
h2 {
content: "All your base are belong to ";
strong {
content: "us";
}
}
Which will output the following HTML:
<h2>All your base are belong to <strong>us</strong></h2>
To import other scripts into the current script, use the @require
keyword followed by the name and path of the script in single or double quotes (['"]
) and terminated with a semicolon (;
). For example:
@require "scripts/header.csss";
The path should always be relative to the file calling it.
Comments work exactly the same as they do in CSS, they open with /*
and close with */
. For example:
/* I'm a comment */
Any CSS property that is not fully supported yet in some (older) browsers and need a prefix to work correctly will be added automatically by the interpreter.
For example, take the animation
property. For most browsers this property will work out of the box, but some older android browsers require the -webkit-
prefix, which will be added automatically.