Adding Style and Behaviour to Web Pages with a dash of Spice icon

Dave Raggett <dsr@w3.org>
February 1998
Revised: May 1999

Abstract

Extensions to HTML become simple to handle with a new language from HP that blends style sheets and scripting. Spice is an amalgam of CSS and JavaScript. HP is developing a free browser as a proof of concept for Spice. HP has submitted Spice to the World Wide Web Consortium, see

http://www.w3.org/TR/1998/NOTE-spice-19980123.html

Handling HTML extensions with Spice

Application developers frequently find the limitations of HTML get in the way. Wouldn't it be nice if you could just add your own tags and write a few lines of script to handle them? Well HP has been busy developing a solution based upon a new way to combine style sheets and scripting, building upon CSS and JavaScript. The result called "Spice" allows you to add new style properties and to define or import support for new ways to render HTML.

Style Sheet Basics

Spice extends JavaScript to add cascading style rules using the same syntax as CSS. The style rules specify the kinds of objects (for instance text, images and form fields), that will be used to render the markup and their properties. To understand how this works you first need to understand how the browser handles the HTML (or XML) markup.

Markup consists of text interspersed with paired start and end tags, for instance <h1> and </h1>. Each pair acts to mark off a section of the document. The browser uses the tags to build a hierarchical representation of the document. This is often called the document parse tree. For XML, this can be done without any prior knowledge of the meaning of the tags. For HTML life isn't so simple, and the browser has to use an empirical knowledge of how HTML tags are used in practice, as this often departs from the official recommendations. Sigh!

The style sheet consists of a set of rules. Each rule has two parts: a left-side giving the pattern that defines which elements in the document it applies to, and a right-side that specifies one or more style properties to be applied to these elements. If more than one rule applies to a given element, the most specific rule will take precedence over less specific rules.

The document is formatted starting with the element at the root (top) of the hierarchy, and then traversing the hierarchy depth-first to find and apply the styles for descendant elements. To make this less abstract here is an quick tutorial.

This is a style sheet written in Spice. It differs from CSS only in a few details caused by the need to make the syntax fit comfortably with JavaScript. It starts by importing the document, block and inline rendering objects. The first rule sets the font family and size for the document. The display property specifies that the html element is to be rendered using a document object, h1 and p elements are to be rendered with block objects, while em elements are to be rendered with inline objects.

import document, block, inline;

style html
{
    fontFamily: "Arial";
    fontSize: 12pt;
    display: document
}

style h1
{
    fontWeight: bold;
    fontSize: 1.5em;
    textAlign: center;
    display: block
}
style p
{
    textAlign: left;
    display: block
}

style em
{
    fontStyle: italic;
    display: inline
}

Here is a sample document, the style sheet can be applied to:

  <html>
    <h1>This is a heading</h1>
    <p>This is normal text</p>
    <p>This is <em>italic</em></p>
  </html>

The style sheet is applied to a document such as the above example by applying the style rule to the root node (html) and then in turn to its descendants. This generates a hierarchy of rendering objects, shown below schematically together with their style properties:

    document     {fontFamily: "Arial"; fontSize: 12pt;}
       block     {fontWeight: bold; fontSize: 1.5em; textAlign: center}
          text
             "This is a heading"
       block     {textAlign: left}
          text
             "This is normal text"
       block     {textAlign: left}
          text
             "This is "
          inline {fontWeight: italic}
             text
                "italic"

Rendering objects inherit style properties from their parent. Changing the font family for the document will change the font used by all of the block objects included in the document. This holds true even after the document has finished loading. If you set style properties via scripts, the document will dynamically reformat itself. For instance by setting:

    document.fontFamily = "Verdana"

Defining new rendering objects

Spice allows you to define rendering objects with the full power of a scripting language. The following example defines a new rendering object derived from the standard rendering object block. It creates a block with a solid border and inserts the text string "Warning!" in the start of its contents:

    class Warning extends block
    {
        method layout(element)
        {
            this.style.borderStyle = solid;
            this.append(new Text("Warning!"));
            ProcessChildren(element, this);
        }
    }

    style warning
    {
        fontSize: 14pt;
        display: Warning
    }

ProcessChildren is a built-in method that iterates through the children of an element in the document parse tree, creating the flow objects named by their display properties and appending them to the current flow.

Classes make it easy to define event handlers using the "when" statement:

    class Link extends inline
    {
        href = "http://www.w3.org/";

        ...

        when onmousedown
        {
            document.load(this.href);
        }
    }

This defines a rendering object class for hypertext links, derived from the class for emphasis. Clicking on a link causes it to load the URL given in its href property. You can use the clas construct to extend rendering objects defined in other languages. This allows you to specify event handlers for such objects.

Other Features

There isn't space here to go into detail on all the features offered by Spice. However here is few of them: Modes provide a way to specify alternate renderings for elements, for instance when creating a table of contents for the document. A similar mechanism can be used for media dependencies. Spice extends JavaScript to objects to be imported from libraries written in Spice, Java or ActiveX.

To encourage interoperability, URLs are used to name libraries that support a given set of rendering objects and style properties. Each library can be implemented in different ways according to the needs of each platform. Rendering objects can be implemented in Java, ActiveX or even Spice. CSS rendering objects are supported via a standard library.

The addition of a standard graphics library will allow rendering objects to be written in Spice that render themselves as text and graphics. For instance exploiting graphical effects for decorating text, something that is currently solved using bitmapped graphics. Rendering objects written in Java can exploit AWT for this purpose.

Spice leverages ongoing work by W3C on Cascading Style Sheets and the Document Object Model for the syntax of style rules, the properties of standard rendering objects and the means for accessing and manipulating the document parse tree.

Further Information

I was invited to present Spice at the SGML UK meeting in Swindon on 31st March 1998. Here are the slides.

For references, further information on Spice, and comparisons with other work, you are recommended to look at the HP Spice submission to W3C.

Dave Raggett <dsr@w3.org> is an engineer at Hewlett Packard's UK Laboratories, and works on assignment to the World Wide Web Consortium, where he is the W3C lead for HTML.