Draft. Date: 16 Feb 1996. URL: http://www.w3.org/pub/WWW/Style/css/css2dsssl.html

Translating CSS to DSSSL

Bert Bos

The present document describes the relationship between CSS and DSSSL by showing what DSSSL flow objects correspond to CSS style properties. However, the description is informal, in that it only indicates the main points. It still requires somebody knowledgeable in DSSSL to create a program that actually produces DSSSL flow objects (or alternatively: a DSSSL style sheet) from an HTML document with a CSS style sheet.

The DSSSL flow tree will sometimes be an approximation instead of an equivalent, because some CSS properties have no corresponding flow object or characteristic in DSSSL. Also, there are some values in CSS that are explicitly defined to be media or context dependent; when mapping them to DSSSL a specific value will have to be substituted and the media-dependency is lost.

The translations provided below are for the final properties of each HTML element instance in the document, after all the cascading and inheritance rules have been applied.

Typographic conventions

The word property applies to a CSS property, anything that is a property will be shown like this. The words characteristic and flow object refer to the things of that name in DSSSL; anything that is a characteristic or a flow object will be shown like this.

A DSSSL expression is shown like this: (+ (* 2 3) (inherited-font-size)).

Overall operation

As said earlier, the translations outlined below are effected on the final property set that results for each element instance in the document, after all the cascading and inheritance rules have been applied.

Assume, for convenience sake, that the document has been transformed into a tree, with each node corresponding to an element and the leaves representing character content or empty elements. Each node contains a full set of CSS properties (i.e., all the properties, even if some of them don't apply this to this particular element).

The DSSSL flow objects are produced by traversing this tree depth-first. For each node, the properties are inspected, one or more flow objects are created and characteristics of existing flow objects or of yet to be created ones are given specific values.

Normally, the flow objects that are created for child elements form a list that is attached to the principal port of one of the flow objects created for the parent. So, for example, a paragraph with three children: <P>One <B>bold</B> word</P> results in a paragraph flow object (paragraph fo) with a list of character fo's attached to its main port.

When characteristics are not mentioned in the text below, they are assumed to have their default values.

The following optional features of DSSSL are required for CSS: [...]

Setting up the window

For on-line display, CSS1 assumes a canvas with a given width and unlimited height. The best way to translate this to DSSSL is to insert a vertical scroll flow object at the top of the produced flow object tree.

The vertical scroll object will have left-margin and right-margin set to 0. The background characteristics will be set from the background property on the BODY element (see below).

CSS object types

In CSS1, there are six types of objects. Two of them are implicit (this will change in CSS2):

The four other types are determined by the display property:

For replaced objects an external graphic fo is created, with the characteristics entity-system-id and notation-system-id set to the URL of the replaced object and a notation for the content type of the external object respectively. If the content type is not known, one could create a notation-id that represents `unknown', something like -//NOTATION unknown//EN.

For block objects a paragraph fo is created. Depending on the values of the background and border-style properties, this fo will either have a list of fo's in its main port, or a single box fo, in which case the list of children will be in the main port of that box fo. This box fo will have display? = #t.

If background is transparent and border-style is none, there will not be a box fo. See under background and border-style below to see what the characteristics of the box fo are otherwise.

List items produce a paragraph fo and optionally a box fo just like block objects, but the list of fo's that is created for the children is prefixed with a line field fo. See the description of list-style below for the characteristics of this fo.

An inline object produces a sequence fo, a box fo or a score fo, or possibly a score fo within a box fo, depending on the values of the background and text-decoration properties.

If background is not transparent and/or text-decoration is box a box fo is created. If text-decoration is underline, overline or line-through, a score fo is created. Otherwise the element results in a sequence fo. See below for the characteristics of the fo's.

CSS1 properties

For each CSS property, the following paragraphs describe how it can be mapped to DSSSL flow objects or DSSSL characteristics.


Sets the font-size characteristic of the present flow object, and, through inheritance, of all its children. The values are mapped as follows:

is copied unchanged.
is replaced by a DSSSL expression like the following: (* (inherited-font-size) p), where p is one hundredth of the percentage.
is replaced by (* (inherited-font-size) (power 1.5 p)), where p is the number. (power is not a primitive in DSSSL, but it can be defined like this: (define power (lambda (x y) (exp (* y (log x))))).)
xx-small, x-small, etc.
mapped to fixed lengths, depending on the context (media) in which the document is to be rendered, e.g., 4pt, 6pt, etc., or maybe to an expression that involves the initial font size.


Maps to font-family-name. The generic families serif, sans-serif and monospaced can be mapped to ISO-serif, ISO-sans-serif and ISO-monospaced. Cursive and fantasy must be mapped to FPIs.


Maps to font-weight, as follows:

extra-light, light, demi-light, medium, demi-bold, bold, extra-bold.
extra-light, light, semi-light, medium, semi-bold, bold, extra-bold.
the number has to be rounded (since DSSSL only accepts discrete values) and added to the inherited value. The apparent complexity comes from the fact that numbers and keywords have to translated back and forth: (number-to-weight (+ (round (* 2 p)) (weight-to-number (inherited-weight)))), where p is the number, and `weight-to-number' and `number-to-weight' are yet to be defined functions that translate between numbers and keywords.


Maps to font-posture, except for the value small-caps:

small-caps and combinations with small-caps
Small caps are handled through a glyph-subst-table. [details?]


Maps to line-spacing: a length maps to itself, a percentage maps to (* (actual-font-size) p), where p is one hundredth of the percentage.


See the individual font-* and line-height properties above.


Maps to color. [Need to define color space somewhere, how is gamma treated? BB]


Each element, when its background is set to a color other than transparent, is wrapped in a box-fo (see CSS object types above). Its box-type is set to background. The background property is then mapped to the background-color characteristic.

A background set to a URI needs a vertical-scoll-fo instead of a box-fo. The background-tile is set to the URI. Any value for <position>, <repeat> or <scroll> must be set on the background-method, the values of which have not yet been standardized in DSSSL.


[something with inline-space-space]


[something with escapement-space-before/after]


(See CSS object types above for the fo's that are created for specific values of text-decoration.) Text-decoration only has effect on inline elements. In that case, it will wrap the contents of the element in another flow object, according to the values:

no effect, don't create another flow object.
underline, overline, line-through
wrap the contents of the element in a score object, with the type characteristic set to before, after and through respectively. CSS doesn't specify values for the other characteristics, so they can be left at their default, although it is suggested that color is set to the value of the color property and line-thickness to 1/10th of the font-size.
wrap the contents in a box object with display set to #f and box-type set to border. [values for other characteristics...]
no standard fo, needs to be mapped to an application dependent fo.


Only applies to inline objects. Vertical-align maps to the position-point-shift characteristic of the sequence fo created for the element. The values map as follows:

0 (i.e., the default)
Find out the subscript position of the inherited font (i.e., the font of the parent element, not the font of the current element) and use that as a value: (font-property (inherited-font) ("ISO/IEC 9541//SUBSCRIPT-POSITION")) [or whatever the name for that property is; BB]. If that value is not available, use some fixed proportion of the inherited font-size, e.g., (* 0.2 inherited-font-size).
Likewise, but for the superscript position. The fixed ratio could be -0.8.
This cannot be expressed in DSSSL.
This cannot be expressed exactly (since the height of the current element is unknown), but when the contents of the current element consists of text in a single font, the following is an approximation: (- (actual-font-size) (inherited-font-size)), i.e., shift up by the difference in font-size between this element and its parent. If the height of ascenders in both fonts is available, use the difference between those instead.
The same problem, but even more so, since the x-height of the inherited font is not necessarily available.
This cannot be expressed in DSSSL.
Again an approximation, useful when the current element contains only text in a single font. If the position of descenders in the current font and the inherited font are known, shift down by the difference between them: (- (font-property font ("ISO/IEC 9541//MAX-DESCENDER")) (font-property (inherited-font) ("ISO/IEC 9541//MAX-DESCENDER"))) [or whatever the properties are called].
(* line-spacing p), where p is 1/100th of the percentage. Example: vertical-align: 50% maps to position-point-shift: (* line-spacing 0.50).


uppercase and lowercase can be handled by setting the value of char-map. Capitalize can maybe be handled during flow object tree construction.


Maps to quadding on paragraph fo's:

left, right
Left maps to either start or end, depending on the writing mode: (if (= writing-mode 'left-to-right) start end). Right is exactly the opposite: (if (= writing-mode 'left-to-right) end start).
center, justify
map to center and justify.


maps to first-line-start-indent. A percentage value can be mapped to (* (display-size) p), where p is one hundreths of the percentage.


When the current element has a box fo, the four padding values can be mapped to the characteristics space-before, end-indent, space-after and start-indent. If the writing mode is right-to-left, start-indent and end-indent have to be swapped.

If there is no box fo and the element is a block, the padding values can be put on the space-before, end-indent, space-after and start-indent characteristics of the element's paragraph-fo or the external-graphic-fo. If the current writing-mode is right-to-left, start-indent and end-indent have to be swapped.

If there is no box-fo and the element is inline, an inlined box-fo will have to be created for it.

margin, margin-*

The four margin values will be set on the space-before, end-indent, space-after and start-indent characteristics of the paragraph fo or the external graphic fo. If the current writing-mode is right-to-left, start-indent and end-indent have to be swapped.

[Describe how small margins adjacent to larger margins are cancelled out, instead of being added together. BB]


See CSS object types above.

width, height

Width and height cannot be mapped to DSSSL, except for external graphic fo's.

If both width and height are auto, set scale to 1.

If width is auto and height is a length: set scale to max-uniform, max-width to infinity (a very large value), and max-height to the given length.

Analogously for height set to auto and width a length.

If both are set to lengths, copy the lengths to max-width and max-heightand set scale to max.

Percentage values [can use (display-size) to get parent's width? BB]

float, clear

Need application-dependent flow objects.


If <border-style> is not none and the object is a block object or list item, the value of <border-style> will be copied to various characteristics of the box fo. When the four edges have different styles they cannot be mapped to DSSSL. When the style is any thick-thin or thin-thick, another box fo has to be nested in the first, to achieve the desired effect. Values beveled and raised cannot be mapped, unless the box-fo is replaced by an application-dependent fo.

If there is a box fo, the value <border-width> is copied to line-thickness. Only when the four sides have the same width can the border be mapped to DSSSL (otherwise, needs a non-standard fo). The keywords thin, medium and thick map to some constants, depending on the environment in which the formatting is done.

<color> maps to the color characteristic of any box fo. <url> cannot be mapped to a characteristic of the box-fo. It needs an application-dependent fo to replace the box-fo.


The list-style property determines what is put into the line field fo that is created for each of the children that are list items (see CSS object types above). [Need to find the appropriate DSSSL expression for the content of the line-field fo. BB]


White-space maps to the lines characteristic of any paragraph fo: normal maps to wrap, pre maps to asis, nowrap maps to asis. [How is the difference between collapsing spaces and keeping them as is expressed in DSSSL? BB]


more to come...

drop caps impossible

text wrap around images impossible

side heads with marginalia?

first-line impossible?

link maps to link object, link pseudo classes not mapped.

list items use line-field?

W3C Bert Bos
Last updated 22 Jul 1996