Personal tools

CSS Description

From OpenLaszlo

This page is out of date relative to the current proposal; see CSS_Proposal for the current proposal.

The <style> tag allows changing the visual look of an application at runtime -- runtime skinning -- but it can be difficult to maintain on large applications, and it has a runtime cost, in startup time and download size. Engineers at Laszlo Systems have implemented an alternate, compile time styling system based on the W3C Cascading Style Sheets standard; however, this implementation wasn't part of the community process, so it's not officially part of OpenLaszlo. This document starts to describe how to use the provisional CSS implementation; it's so new that we don't have best practices yet.

CSS in OpenLaszlo is fast and powerful, but complicated.

An lzx file can have a cssfile attribute on the canvas. The CSS file must be valid W3C CSS. A CSS file is composed of rules. Rules have a selector and a set of attributes. The selector selects which objects get these attributes. The attributes are easy to understand; the selectors are hard.

The value of an attribute in a css file is substituted into the attribute's value in the lzx file, at compilation time. It may sound crazy, but this is similar to the #define macro in the C preprocessor. Anything that fits within two quotation marks in the CSS file can go into an attribute's value. Any attribute of an lzx object can be changed with CSS, but only at compile time. Unlike W3C CSS, which defines particular attributes on particular document elements, Laszlo CSS is casual. Override any attributes you like on any element. If you break the schema you'll get a compiler warning, but go right ahead.

So that's attributes; selectors are the hard part.

The simplest selector uses ids.

#b3 /* selects any object with id="b3" */

Another simple selector is names:

[name="b1"] /* selects any object with the name "b1" */

More complicated selectors refer to the structure of the views:

mybox[name="b2"] /* selects any instance of mybox whose name is "b2" */

...and to the view hierarchy

view[name="outerbox"] mybox /* Any mybox within a view named outerbox */ 

So why use it? CSS lets you separate the structure of an application from the attributes of the objects in that application. The "application" code can be very simple:

<mybox name="b1" />
<mybox name="b2" />
<mybox id="b3" />
<mybox mytag="special"/>
<view name="outerbox" >
   <mybox />
</view>

Combine this with a fairly readable stylesheet:

/* Any element with a name "b1" */ 
[name="b1"] {
   innerfill : "0x6E967A";
   strokecolor : "0x1A3024";
}
/* A "mybox" element with the name "b2" */ 
mybox[name="b2"] {
   innerfill : "0x246147";
   strokecolor : "0x1A3024";
}
/* Any object with the id b3 */ 
#b3 {
   innerfill : "0x1A3024";
   strokecolor : "0x1A3024";
}
/* Any object with the attribute mytag equal to special */ 
[mytag="special"] {
   innerfill : "0x5C705E";
   strokecolor : "0x000000";
   height     : 150;
}
/* A view named outerbox */ 
view[name="outerbox"] {
   bgcolor : "0xCAC8D5";
   width : 90;
   height: 200;
   
}
/* Any mybox within a view named outerbox */ 
view[name="outerbox"] mybox {
   x: 20;
   y: 20; 
   strokecolor : "0x1A3024";
   innerfill : "0xC4D1C4";
   height: "${parent.height-40}";
   width: 50;
}


We get a variety of different-looking boxes. This is just the beginning of what's possible with CSS. A few more possibilities:

  • Move "hardcoded" strings from lzx into CSS, then give the CSS to your copy editor to perfect the strings, or translate them to another language.
  • Create an approximate layout using CSS values for x, y, width, and height, then give the CSS and the lzx to a designer to perfect the positioning.
  • Separate application logic from layout logic by moving constraints into CSS. This goes beyond what CSS is supposed to be about, but it ends up being useful; see the height attribute on the outerbox selector in the above example.

[_pw9_]

nvnv