Nleyten

To content | To menu | To search

Tag - ccss

Entries feed

Thursday 22 May 2014

Announcing CCSS 1.5

CCSS is a preprocessor/pretty-printer for CSS (Cascading Style Sheets), extending the language with support for variables and arithmetic. Version 1.5 of is out now, and is already available in OPAM, for your convenience.

This version features support for @keyframes (CSS3 animations). And of course, you may take advantage of CCSS's variables to make your keyframe declarations easier to maintain. Consider, for example, the source below:

Inflexion_point: 50%;
@keyframes test
{
from                    {opacity: 0;}
Inflexion_point         {opacity: 0.5;}
Inflexion_point + 1%    {opacity: 0.6;}
to                      {opacity: 1;}
}

And the corresponding output from CCSS:

@keyframes test
{
from
{
opacity: 0;
}
50%
{
opacity: 0.5;
}
51%
{
opacity: 0.6;
}
to
{
opacity: 1;
}
}

This version also brings a change to the internal AST representation that though minor, is bound to raise a few eyebrows, and thus requires a brief explanation. In CSS, the @charset at-rule is special in the sense that if present, it may only appear at the very start of the file. In previous versions, CCSS's AST encoded this requirement by treating @charset differently than other at-rules. In this new version, this is no longer the case. The end result is a cleaner and more concise AST, but it does mean that CCSS will now accepted @charset statements beyond the start of the file.

Before you cry "regression", bear in mind that CCSS was never meant to be a standards compliant CSS parser nor a CSS lint. The tool will happily accept semantically meaningless CSS while simultaneously rejecting perfectly valid CSS (it requires declaration blocks to always be terminated by a semicolon, for example, which the standard does not). Therefore, making CCSS slightly less standards-compliant is a viable option if the upside is a simpler, saner, and easier to maintain grammar. Having said that, in practice you won't find many incompatibilities, and I'll happily fix any egregious ones.

Monday 7 October 2013

Announcing CCSS 1.4

I've recently released version 1.4 of CCSS, a preprocessor/pretty-printer for CSS (Cascading Style Sheets). Though CCSS most definitely falls into the category of software developed to scratch a personal itch, it has gained other users in the meantime. Consequently, I reckon a few words are in order concerning the features/idiosyncrasies of this tool.

For those not familiar with CCSS or CSS preprocessors in general, the basic rationale for these tools is to fill some glaring shortcomings in the vanilla CSS language, namely the lack of variables and basic arithmetic operations. Many tools go further still, providing new ways to structure and organise CSS declarations.

There is certainly no lack of CSS preprocessors available, most of which have large user bases and plenty of fancy features. So, why CCSS? Does the world really need yet another CSS preprocessing tool? I cannot speak for the world. I can, however, relate that some years ago I was in need of a CSS preprocessor that supported variables, arithmetic, and did not choke on the few CSS3 constructs I was introducing into my stylesheets. Moreover, I was looking for a nice, clean syntax that felt like a natural extension to vanilla CSS. Finally, I don't think it was unreasonable to expect that a tool performing such a simple task to be fast. Unfortunately, the tools I tried back then did not quite meet these requirements, particularly where speed was concerned.

OCaml hackers being who they are, I reckoned that a better tool for my needs could be written in a weekend. And that's how CCSS was born. Fortunately, I was about right concerning the time estimate, which just goes to show how awesome the OCaml language and assorted tools (namely Menhir and Ulex) are for writing compilers.

This little history brings us to the most important point about CCSS that potential users should be aware of: it was never meant to be a fully-compliant superset of vanilla CSS. To illustrate this point, consider the humble semicolon, which according to the CSS spec is a declaration separator, and optional after the last declaration in a block. Omitting the last semicolon is, however, a brittle practice (it's all too easy to forget to add the semicolon when a new declaration is appended to the block), which is why users are advised to always write a semicolon at the end of each declaration, effectively treating it as a declaration terminator. Guess what? The CCSS grammar treats the semicolon as a mandatory terminator — spec be damned.

Variables are perhaps the most useful extension to CSS, and CCSS does support them. In previous versions, variables could only be assigned to expressions. The recently released version 1.4, however, introduces the possibility of assigning a whole declaration block to a variable. This feature is similar to what other preprocessors term mixins, so this is the nomeclature I'm using too.

The example shown below illustrates the use of variables to declare commonly used expressions. Note that syntactically, variable identifiers are distinguished by starting with a mandatory uppercase letter. This was chosen to make tooling (such as syntax highlighting in editors) easier.

Foo: 20em;
Bar: 1px solid black;
h1
{
width: Foo;
border: Bar;
}

The second example concerns the use of variables to declare mixins, ie, declaration blocks that can be included within subsequent declaration blocks:

Inverse_scheme:
{
color: #fff;
background: #000;
}
h1
{
Inverse_scheme;
font-weight: bold;
}

CCSS also extends CSS expressions with basic arithmetic operations (addition, subtraction, multiplication, and division). The operands must be CSS quantities (either dimensionless or with an attached unit), or other expressions that ultimately resolve into a quantity. Moreover, variables whose value is a quantity (or an expression which resolves into a quantity) may also be used as operand.

The operators are '+', '-', '*', and '÷'. Note that multiplication and division have precedence over addition and subtraction, but you may use parentheses to group operations. In addition, the choice of the non-ASCII character '÷' as division operator betrays CCSS's origins as tool designed to scratch a personal itch: it can be input with just a few easy-to-remember keystrokes in VIM, the editor I use. I had thus no motivation to find an ugly multi-character token to represent it. Consider thus the following input:

Left: 10em;
Right: 5em;
Total: Left + Right;
h1
{
padding: (1.5em + 0.5em) * 2;
width: 2 * Total;
}

CCSS will produce the following output:

h1
{
padding: 4em;
width: 30em;
}

The reader will have noticed that CCSS must be unit-aware when performing arithmetic. As a matter of fact, the programme performs a basic sanity check of units, and will complain if you try, for example, to add "1em" with "10px". By default, CCSS will not make any attempt to convert units even if they are convertible, such "cm" and "mm". If you wish for CCSS to attempt unit conversion, please provide option "--convert" on the command line (short version "-c").

Units can be grouped into four categories, and conversion is possible if the units belong to the same category. Upon conversion, the result will be the same unit as the first operand. The categories and corresponding units are as follows:

  • length: mm, cm, in, pt, pc
  • angle: deg, grad, rad
  • time: ms, s
  • frequency: hz, khz

As an illustration of unit conversion, the result for all the following arithmetic operations is the same, "2in":

h1
{
foo1: 1in + 1in;
foo2: 1in + 2.54cm;
foo3: 1in + 25.4mm;
foo4: 1in + 72pt;
foo5: 1in + 6pc;
}

And that's it! Note that the project's development has recently moved to GitHub, so fork away!