3 Embedding CSS in Scheme

This section describes a syntax for creating CSS stylesheets in WebIt!. What is described here aims at supporting full CSS1.

3.1 A Basic Example

In this section, I illustrate a basic example of the embedding. We create a simple HTML document which uses an external CSS stylesheet. The CSS stylesheet is used to color the background navy, and set different text fragments yellow, white, and red.

(require (lib "xml.ss" "webit") (lib "html.ss" "webit") (lib "css.ss" "webit"))

The css syntax creates a CSS stylesheet. Informally, css takes a list of rules, each of which consists of a selector and a property list. In the first rule, for example, the selector is body, and the property list includes settings for font-family, font-size, and background-color.

(define
 ex-css
 (css
  (body
   (font-family "sans-serif")
   (font-size "12pt")
   (background-color "navy"))
  (p (color "white"))
  (p.ex (color "red"))
  (h1 (color "yellow"))))

This creates the following stylesheet:

  body {
    font-family: sans-serif;
    font-size: 12pt;
    background-color: navy;
  }
  p {
    color: white;
  }
  p.ex {
    color: red;
  }
  h1 {
    color: yellow;
  }
(define
 ex
 (h4:html
  (h4:head (css-link "a.css") (h4:title "Stylesheet Example"))
  (h4:body
   (h4:h1 "Stylesheet Example; this text is yellow")
   (h4:p "This text is white")
   (h4:p h4:class: "ex" "This text is red"))))
(write-xml ex-css (open-output-port "a.css"))
(write-xml ex (open-output-port "a.html"))

In the HTML above, we can see the use of the css-link form, which takes a single argument, the URL of the external stylesheeet. This form is simply shorthand for the construction of the following HTML:

(h4:link h4:rel: "stylesheet" h4:href: "a.css" h4:type: "text/css")

3.2 Simple selectors, Classes, and Pseudo-classes

The simplest form is the simple selector:

   p { color: white; }

The simple selector is just a symbol that is the element type to which this style property applies. This is written as:

(css (p (color "white")))

3.2.1 Classes

Elements can also be selected by "class", that is, by the value of the HTML "class" attribute:

   .ex {color: red;}

This is written as:

(css (.ex (color "red")))

This is a convenient notation--and one which is supported by PLT. But not all Scheme's support symbols which begin with a ".". This example can also be written in a more verbose form:

(css ((class ex) (color "red")))

A selector can also be written with both an element type and a class.

   p.ex {color: red; }

This is written as:

(css (p.ex (color "red")))

or, in the verbose notation:

(css ((class p ex) (color "red")))

Using PLT's "infix" notation, this last can also be written as:

(css ((p . class . ex) (color "red"))))

if that is to one's taste.

3.2.2 Pseudo-classes

Pseudo-classes are supported in a similar manner. One can color a visited link "lime":

   a:visited { color: lime; }

which is written as:

(css (a:visited (color "lime")))

or, in the verbose notation:

(css ((pclass a visited) (color "lime")))

or

(css ((a . pclass . visited) (color "lime"))))

As with classes, a selector may include only a pseudo-class:

   :visited { color: lime; }

which is written as:

(css (:visited (color "lime")))

or as

(css ((pclass visited) (color "lime")))

3.2.3 Combining Classes and Pseudo-classes

Lastly, classes and pseudo-classes can be combined:

   a.external:visited { color: blue; }

which is written as:

(css (a.external:visited (color "blue")))

or

(css ((pclass (class a external) visited) (color "blue")))

This selector, without the element type, can also be used:

   .external:visited { color: blue; }

which is written as:

(css (.external:visited (color "blue")))

or

(css ((pclass (class external) visited) (color "blue")))

3.3 Id as a Selector

One may attach unique "identifiers" to HTML elements, using the id attribute. The value of an id attribute may be used as a selector as well.

To match the following paragraph tag:

   <p id=z98y>Wide text</p>

the following style rule can be defined:

   #z98y { letter-spacing: 0.3em; }

This would be written as:

(css ((id z98y) (letter-spacing "0.3em")))

(In principle, "(id z98y)" can also be written as the symbol "|#z98y|".)

Id's may also be combined with an element type in a selector:

   h1#z98y {letter-spacing: 0.5em; }

written as:

(css ((id h1 z98y) (letter-spacing "0.5em")))

or

(css ((id h1 z98y) (letter-spacing "0.5em")))

3.4 Contextual Selectors

CSS allows one to specify that a "style" applies only to selected elements, in a _context_. For example, if I want to color emphasized text red, but only within an h1 element, this can be written as:

   h1 em { color: red; }

which, in the WebIt! embedding, is given as:

(css ((// h1 em) (color "red")))

The keyword "//" is used to suggest a similarity of a contextual specifier with a "path expression" (as in XPath/SXPath).

The "steps" in a contextual specifier can be an element type, class, pseudo-class, an id, or a combination of these.

3.5 Grouping Selectors

To avoid duplicating style descriptions, selectors may be grouped together. Any of the above kinds of selectors may be grouped, as shown below, where a simple selector (an element type) and a contextual selector are grouped:

    h1, h2 b, h2, em { color: red; }

The grouping "operator" is just a list:

(css ((h1 (// h2 b) (// h2 em)) (color "red")))

3.6 Importing a stylesheet

A stylesheet may import another stylesheet:

    @import url(http://somewhere/a.css)

This is written as

(css (import "http://somewhere/a.css") ...)

Any such import forms must appear at the beginning of a CSS stylesheet, before any "style rules".

3.7 Marking a Property "Important"

CSS allows designers to increase the "weights" of some property declarations:

    p { font-size: 12pt ! important;
        font-style: italic;
      }

This can be written in Scheme as:

(css (p (! (font-size "12pt")) (font-style "italic")))

3.8 Grammar for WebIt!'s css form

In this section, we give a grammar for the css form of WebIt!.

 external-css-stylesheet ::= (css import-clause* rule+)
 internal-css-stylesheet ::= (css/html import-clause* rule+)
 
 import-clause ::= ( import string )
 
 rule ::= ( complex-selector css-avp+ )
 
 complex-selector ::= single-selector |
                      grouping-selector
 
 simple-selector ::= symbol |
                     (class symbol) |
                     (class symbol symbol) | -- form is (class  )
                     (pclass symbol) |
                     (pclass symbol symbol) | -- form is (pclass  <
 pseudo-class>)
                     (id symbol) | 
                     (id symbol symbol) -- form is (id  )
 
 path-selector ::= ( // simple-selector+ )
 
 single-selector ::= simple-selector |
                     path-selector
 
 grouping-selector ::= ( single-selector+ )
 
 css-avp ::= ( symbol scheme-expression ) |
             (! (symbol scheme-expression))

Note 1: scheme-expression must evaluate to a string

Note 2: internal-css-stylesheet translates to

(style type: "text/css" (css import-clause* rule+))

3.9 A Few More Examples

These are taken from the stylesheet used in the HTML version of the MzScheme manual, shown in this notation proposed by WebIt!.

(css
 ((h1 h2 h3 h4 h5 h6) (margin-top ".5em"))
 (.partheading (font-size "90%"))
 (.chapterheading (font-size "90%"))
 ((// ol ol ol) (list-style-type "lower-roman"))
 ((// .scheme .keyword) (color "black") (font-weight "bold"))
 ((// .scheme .builtin) (color "#990000")))

The resulting CSS output is given below:

 h1,h2,h3,h4,h5,h6 {
     margin-top: .5em;
  }
 
  .partheading {
     font-size: 90%;
  }
 
  .chapterheading {
     font-size: 90%;
  }
 
  ol ol ol {
     list-style-type: lower-roman;
  }
 
  .scheme .keyword {
     color: black;
     font-weight: bold;
  }
 
  .scheme .builtin {
     color: #990000;
  }

Last modified: Sunday, January 30th, 2005 1:57:37pm
HTML generated using WebIt!.