Table of contents
There are some recurring proposals for CSS that get rejected because they don't need to be implemented on client-side or browser vendors may abuse them. These are:
- constants/variables
- expressions
- browser-specific styles
and here's the best part: I've started implementing them in a way that is compatible with all current browsers.
How does it work?
It's a server-side PHP5 script that parses extended CSS files, filters them and outputs valid W3C CSS stylesheets (outputs without any unnecessary whitespace, so you get light compression as a bonus).
It's not just simple regex hack. It's a real parser with CSS-specific error recovery. It even passes Acid2 test :)
Sytax is based on CSS2.1 CR—20040225. It's extended to accept some CSS3 and…
Goodies
You can write expressions instead of simple CSS terms. Just add extra parentheses:
margin-left: (200px * 3/2 – 10px);
You can define constants:
@define
{
menu-height: 4em;
gutter: 15px;
sidebar-width: (200px – gutter);
}
and use them in expressions:
#maincontent
{
padding: (menu-height) 0 0 (sidebar-width + 10px);
}
You can include files, anywhere in stylesheet. Included files are parsed as individual files, but they all share variables (this behavior might be configurable in future).
@include "file.css";
C++ comments are recognized (parser does not preserve comments except Mac IE comment backslash hack).
foo {bar: baz} // quz!
Catches
- It's not possible to reliably implement server-side conversion between em/cm/px/%, so you can't mix them in expressions.
- You must put spaces around minus sign to avoid confusion with identifiers.
There is no public download available at the moment. The script is not ready for big time. Send me an e-mail if you want to play with the script.
Live examples
Compare:
Notes
About this implementation
Speed of this script is not an issue. It's fast enough for development, and for production sites you should use generated static CSS files anyway.
Script uses PHP5 OO features. It might be possible to change few things (most notably remove error recovery code) to get basic PHP4—compatible version, but I won't bother to do that.
CSS compression is achieved only by removal of optional whitespace and don't expect more. There are very few cases when CSS can be safely shortened, that is without affecting cascade, inheritance or running into browser bugs.
Expressions are lazily evaluated.
General parser issues
Names with hyphens are horribly confusing. I'd like to replace hyphen with a period, but that's tricky — in CSS hyphenated identifiers are a single token, so any solution to this problem would involve inelegant hacks or major changes to CSS grammar.
Single flat namespace for variables is acceptable if you name your variables in organized way (menu-heading-height, sidebar-link-color, etc.).
Structures
The next step is to add structures. Compare:
margin: (example-margin-top) (example-margin-right) (example-margin-bottom) (example-margin-left);
margin: (example-margin);
These cannot be simply arrays. Parser must know type of structure to reliably access its elements:
background: (example-background);
padding-left: (example-background-position);
TODO
- syntax + implementation of browser specific hacks
- unicode support
- emulation of min-width/min-height properties for IE/win
- has-layout, easy-clearing properties?
- separate css2 and extensions in parser
- hacks as configurable, stackable filters?
- getting width/height from url(image)
Ideas
nc
border:0; border-right:nc;
is
border-left:0;border-top:0;border-bottom:0;
In
in #menu {
. {}
li {}
a {}
}
equals
#menu {}
#menu li {}
#menu a {}
Variant
@define {myFontSize: 14px;}
@define body.large {myFontSize: 20px;}
foo {font-size: (myFontSize);}
equals
foo {font-size: 14px;}
body.large foo {font-size: 20px;}