Introduction
CSSToXSLFO is a tool which converts an XML document, combined with a CSS2 style sheet, into an XSL-FO file. It has some special provisions for XHTML, which is also an XML vocabulary. The tool implements a reasonable subset of CSS2. It also adds a few extensions for handling page-related issues properly. Note that the tool is not a general-purpose printing tool for any kind of HTML pages you can find on the Internet.
The goal of CSSToXSLFO is to provide a rather easy interface to fine printing environments that use XSL-FO as their input. It is a compromise between the simplicity of style sheet expression and the quality of the result. XSL-FO is quite difficult. Writing style sheets that produce it are mostly written in XSLT, which is not straightforward to everyone either. CSS on the other hand is rather simple and yet it is powerful. In fact it combines element selection and formatting specification in one easy-to-learn syntax. The cost is that a lot of interesting XSL-FO features are not available.
An area where the tool can be a plus is the programmatic generation of reports within applications. The variety in style for reports is not that great. The offered feature set of CSSToXSLFO can be sufficient. Having report programmers learn XSL-FO and XSLT is not always an option, while many know CSS and XHTML well enough to be productive with it.
Another use-case for CSSToXSLFO is writing documents in XML. One can put work in a style sheet once and reuse that through the mark-up paradigm, in which content and formatting are separated. The formatting features should be sufficient to produce day-to-day documents in a typical business environment. Such documents don't tend to be very complicated, with respect to layout that is.
In Practice
Specifying Style Sheets
The most general way of specifying a style sheet for a document with CSSToXSLFO is the proposal in section 2.2 of [CSS2]. It consists of a processing instruction, which precedes the document, looking like this:
<?xml-stylesheet type="text/css" href="style.css"?>
For XHTML there are a few additional options. You can
use the link
element to link a style sheet (only persistent style
sheets) to the document or you can embed it with the style
element.
The style
attribute is also available as specified in
[XHTML].
Running It
There are six packages you can run from the command-line: one that produces plain XSL-FO, one that returns the output of XEP, a product from RenderX (http://www.renderx.com), another that returns the output of XSLFormatter, a product from Antenna House (http://www.antennahouse.com), yet another that returns the output of Xinc, a product from Lunasil LTD (http://www.lunasil.com) and finally, two that run FOP (http://xml.apache.org/fop/). One is for version 0.20.5 and the other for version 0.92beta. The 0.20.5 one comes with a filter that removes a few properties, which are not supported by FOP. This makes FOP complain less.
You need JDK1.3 or higher to run the packages. For 1.3 you should create a classpath with a namespace-aware XML parser and an XSLT processor. The command-lines look as follows for plain CSSToXSLFO:
> java -jar css2xslfo.jar url_or_filename <options>
For XEP3:
> java -Dcom.renderx.xep.ROOT=<XEP location> -jar css2xep.jar url_or_filename <options>
For XEP4:
> java -Dcom.renderx.xep.CONFIG=<XEP location>/xep.xml -jar <XEP location>/lib/css2xep.jar url_or_filename <options>
For XSLFormatter:
> set dynamic library path to <XSLFormatter location>/lib > set environment variable AH_FONT_CONFIGFILE to <XSLFormatter location>/etc/font-config.xml > java -jar <XSLFormatter location>/lib/css2xsl.jar url_or_filename <options>
For Xinc:
> java -jar css2xinc.jar url_or_filename <options>
For FOP 0.20.5:
> java -jar css2fop.jar url_or_filename <options>
For FOP 0.92beta:
> java -jar css2fopnew.jar url_or_filename <options>
Additional system properties and/or enviroment variables can be set. Please consult the product-specific documentation for this.
In order for css2xep.jar to work, you should place it in the <XEP
location>/lib directory and create a link to or a copy of your XEP JAR file
with the name xep.jar
. Since XEP4 the link or copy are no longer
needed, because the XEP JAR file has the expected name.
For css2xsl.jar to work, you should place it in <XSLFormatter location>/lib.
The css2fop.jar file needs to be next to fop.jar, which should be next
to the packages is uses. Therefore you should copy fop.jar from the FOP build
directory to its lib directory. The css2xinc.jar should be in the XINC lib
directory.
CSSToXSLFO uses the XSLT-processor that comes with the JDK1.4, which is Xalan from Apache. For better performance you can prepend Xalan 2.6.0+ or Saxon 8.3+ to your boot classpath as follows (assuming /usr/local as the installation directory of Xalan):
> java -Xbootclasspath/p:/usr/local/xalan-j_2_6_0/bin/xalan.jar -jar css2xslfo.jar url_or_filename <options>
You can also use JDK1.5, which comes with a faster XSLT processor.
For XEP there is a special note. You have to specify another XSLT processor, because XEP uses Saxon 6.5.x, with which it doesn't work. You can either prepend another XSLT processor to the boot classpath or you can simply copy saxon8.jar in the XEP lib directory.
Common Options
The following options are common to all six variants. The document to be processed can be specified with a URL or filename. If it is omitted, stdin will be read.
- -baseurl <URL>
- Change the base URL of the input document. By default it is the URL of the document itself.
- -c <URL or filename>
- Specify a catalog in the format defined by SGML Open Technical
Resolution TR9401:1997. Only the
PUBLIC
andSYSTEM
keywords are supported. - -h
- Display the command-line syntax.
- -p <comma-separated list of URLs or filenames>
- A list of pre-processing XSLT style sheets that are executed on the input document, in the specified order, before anything else.
- -uacss <URL or filename>
- Use another User Agent style sheet than the one built-in.
- -v
- Turn on XML validation of the input document.
- parameter=value
- Specify User Agent parameters. Equivalent CSS constructs precede these.
Options Specific To css2xslfo.jar
- -debug
- Produces a number of intermediary files representing the different processing steps.
- -fo <filename>
- The XSL-FO output file. If it is omitted stdout will be written instead.
Options Specific To css2xep.jar
One the following options should be specified.
- -pdf <filename>
- The PDF output file.
- -ps <filename>
- The PostScript output file.
- -config <URL or filename>
- The XEP configuration file.
- -q
- Makes XEP silent.
Options Specific To css2xsl.jar
- -pdf <filename>
- The PDF output file. This option is mandatory.
Options Specific To css2fop.jar
- -fc <filename>
- A user configuration file.
- -pdf <filename>
- The PDF output file.
- -ps <filename>
- The PostScript output file.
- -q
- Makes FOP silent.
- -svg <filename>
- The SVG output file.
Options Specific To css2fopnew.jar
- -fc <filename>
- A user configuration file.
- -pdf <filename>
- The PDF output file.
- -ps <filename>
- The PostScript output file.
- -svg <filename>
- The SVG output file.
Options Specific To css2xinc.jar
One the following options should be specified.
- -pdf <filename>
- The PDF output file.
User Agent Parameters
The User Agent parameters are common to all three packages. They have
no effect if there are @page rules in the style sheet, except for the
rule-thickness
parameter. Furthermore, equivalent CSS constructs, when
present in the style sheet, always precede.
- column-count
- The number of columns on a page. The default is
1
. - country
- The country code. The default is
GB
. - font-size
- The point size of the font. The default for paper sizes
a5
andb5
is10pt
. For all other paper sizes the default is11pt
. See also thepaper-size
parameter. - html-header-mark
- An HTML element can be passed here. Its contents will be used as the running header. By default there is no mark.
- language
- The language code. The default is
en
. - odd-even-hift
- The amount by which the page contents is shifted in the inline
progression direction when the paper mode is
twosided
. The default is10mm
. See also thepaper-mode
parameter. - orientation
- The allowed values are
portrait
, which is the default, andlandscape
. - paper-margin-bottom
- The bottom margin of a page. The default is
0mm
. - paper-margin-left
- The left margin of a page. The default is
25mm
. - paper-margin-right
- The right margin of a page. The default is
25mm
. - paper-margin-top
- The top margin of a page. The default is
10mm
. - paper-mode
- The allowed values are
onesided
, which is the default, andtwosided
. - paper-size
- The allowed values are
a4
, which is the default,a0
,a1
,a2
,a3
,a5
,b5
,executive
,letter
andlegal
. - rule-thickness
- The default thickness for rules when there was no CSS specification
for it. The default is
0.2pt
. - writing-mode
- The XSL-FO writing mode. The default is
lr-tb
. Other possible values arerl-tb
,tb-rl
,lr
,rl
andtb
. See also [XSL-FO].
Building CSSToXSLFO
The tool comes with an ANT file.
The default target only builds the css2xslfo.jar file. Then there are also the
xep
, xsl
, xinc
, fop
and
fopnew
targets, which produce css2xep.jar, css2xsl.jar,
css2xinc.jar, css2fop.jar and css2fopnew.jar respectively.
Ant Tasks
In each package there is a corresponding Ant task. The following table gives the respective class names.
Package | Ant task class name |
---|---|
css2xslfo.jar | be.re.css.ant.CSSToXSLFO |
css2xep.jar | be.re.css.ant.CSSToXEP |
css2xsl.jar | be.re.css.ant.CSSToXSLFormatter |
css2fop.jar | be.re.css.ant.CSSToFOP |
css2fopnew.jar | be.re.css.ant.CSSToFOPNew |
css2xinc.jar | be.re.css.ant.CSSToXinc |
Common Options
All tasks support the nested elements parameter
and
preprocessor
. With the former the parameters described in
User Agent Parameter
can be specified through its
name
and value
attributes. With the latter a sequence
of pre-processing XSLT style sheets can be provided. Its
stylesheet
attribute should be set to a filename or URL.
The following attributes are common to all tasks.
Attribute | Description | Required |
---|---|---|
baseurl | Change the base URL of the input document. By default it is the URL of the document itself. | No |
catalog | Specify a catalog in the format defined by SGML Open Technical
Resolution TR9401:1997. Only the PUBLICand SYSTEMkeywords are supported. |
No |
input | The input document as a URL or filename. | Yes |
output | The output document as a filename. The format is derived from its extension. | Yes |
useragentstylesheet | Use another User Agent style sheet than the one built-in. | No |
validate | Turn on XML validation of the input document. Defaults to
false . |
No |
Options Specific To css2xep.jar
Attribute | Description | Required |
---|---|---|
config | The XEP configuration file. It may be a filename or a URL. | No |
quiet | Makes XEP silent. | No |
Options Specific To css2fop.jar
Attribute | Description | Required |
---|---|---|
config | A user configuration file. | No |
quiet | Makes FOP silent. | No |
Options Specific To css2fopnew.jar
Attribute | Description | Required |
---|---|---|
config | A user configuration file. | No |
Compliance With CSS2
Specifications
Section | Implemented | Remarks and restrictions |
---|---|---|
4.1 Syntax | yes | Thanks to Flute. |
4.2 Rules for handling parsing errors | partial | Unknown properties will end up in the XSL-FO file and cause errors in a XSL-FO processor. |
4.3 Values | yes | Thanks to Flute. |
4.4 CSS document representation | yes | Thanks to Flute. |
5 Selectors | partial | All sections but 5.11.2 and 5.11.3. The
:first-letter pseudo element is implemented with the restriction
that letter combinations, which are considered as one letter, are not examined.
As a workaround you can use the ligature Unicode characters instead. The
vertical-align is also valid when float is
none . In that case it applies to the inline material which is
affected by the pseudo element. |
6 Assigning property values, Cascading and Inheritance | yes | |
7 Media types | yes | By design, only types all and print
are supported. |
8 Box model | yes | |
9.1.1 The viewport | no | |
9.1.2 Containing blocks | yes | |
9.2.1 Block-level elements and block boxes | partial | Compact and run-in boxes are not supported. |
9.2.2 Inline-level elements and inline boxes | partial | Compact and run-in boxes and inline tables are not supported. |
9.2.3 Compact boxes | no | |
9.2.4 Run-in boxes | no | |
9.2.5 The 'display' property | partial | See property table. |
9.3 Positioning schemes | yes | |
9.4 Normal flow | yes | |
9.5 Floats | yes | |
9.6 Absolute positioning | yes | |
9.7 Relationships between 'display', 'position', and 'float' | yes | |
9.9 Layered presentation | yes | |
9.10 Text direction: the 'direction' and 'unicode-bibi' properties | yes | |
10 Visual formatting model details | partial | See the property table for the height property. |
11 Visual effects | yes | |
12.1 The :before and :after pseudo-elements | yes | |
12.2 The 'content' property | yes | |
12.3 Interaction of :before and :after with 'compact' and 'run-in' elements | no | |
12.4 Quotation marks | yes | |
12.5 Automatic counters and numbering | yes | |
12.6.1 Markers: the 'marker-offset' property | yes | |
12.6.2 Lists: the 'list-style-type', 'list-style-image', 'list-style-position', and 'list-style' properties | partial | The list-style-image property is not supported. See also the property table. |
13.2.1 Page margins | yes | |
13.2.2 Page size: the 'size' property | yes | |
13.2.3 Crop marks: the 'marks' property | no | |
13.2.4 Left, right, and first pages | yes | |
13.2.5 Content outside the page box | yes | |
13.3 Page breaks | partial | Named pages are only supported for block-level and table
elements, which are not inside of a table and have an ancestor with the
region property set to body . |
13.4 Cascading in the page context | yes | |
14 Colors and Backgrounds | yes | |
15 Fonts | partial | @font-face and descriptors are not supported. |
16 Text | yes | |
17 Tables | partial | Inline tables are not supported. Anonymous table objects are only supported for missing table groups and missing table cells in a row, on the condition that there are table column elements. Audio rendering is not supported. |
18 User interface | no | |
19 Aural style sheets | no |
Properties
Property | Implemented | Remarks and restrictions |
---|---|---|
azimuth | no | |
background | yes | |
background-attachment | yes | |
background-color | yes | |
background-image | yes | |
background-position | yes | |
background-repeat | yes | |
border | yes | |
border-bottom | yes | |
border-bottom-color | yes | |
border-bottom-style | yes | |
border-bottom-width | yes | |
border-collapse | partial | Not for inline-table . |
border-color | yes | |
border-left | yes | |
border-left-color | yes | |
border-left-style | yes | |
border-left-width | yes | |
border-right | yes | |
border-right-color | yes | |
border-right-style | yes | |
border-right-width | yes | |
border-spacing | partial | Not for inline-table . |
border-style | yes | |
border-top | yes | |
border-top-color | yes | |
border-top-style | yes | |
border-top-width | yes | |
borded-width | yes | |
bottom | yes | |
caption-side | yes | |
clear | yes | |
clip | yes | |
color | yes | |
content | yes | |
counter-increment | yes | |
counter-reset | yes | |
cue | no | |
cue-after | no | |
cue-before | no | |
cursor | no | |
direction | yes | |
display | partial | The values run-in , compact
and inline-table are not supported. The marker value
is supported with the limiation that the value auto for the
width property is not. Markers also don't work with floats. |
elevation | no | |
empty-cells | yes | |
float | yes | |
fonts | yes | |
font-family | yes | |
font-size | yes | |
font-size-adjust | yes | |
font-stretch | yes | |
font-style | yes | |
font-variant | yes | |
font-weight | yes | |
height | partial | A percentage value for the height of a block, which is in another
block with an explicit height, will be treated as auto . This stems
from the fact that in this case a block has to be split in a fo:block-container
and a nested fo:block, because there are properties that don't apply to both of
them. The inner original block will therefore have a parent without an
explicit height specification. The latter has moved to the surrounding
fo:block-container. |
left | yes | |
letter-spacing | yes | |
line-height | yes | |
list-style | partial | See individual properties. |
list-style-image | no | |
list-style-position | partial | A list should be uniform. Specifying different values for different list items will produce undesired results. |
list-style-type | partial |
Only the values A list should be uniform. Specifying different values for different list items will produce undesired results. |
margin | yes | |
margin-bottom | yes | |
margin-left | yes | |
margin-right | yes | |
margin-top | yes | |
marker-offset | yes | |
marks | no | |
max-height | yes | |
max-width | yes | |
min-height | yes | |
min-width | yes | |
orphans | yes | |
outline | no | |
outline-color | no | |
outline-style | no | |
outline-width | no | |
overflow | yes | |
padding | yes | |
padding-bottom | yes | |
padding-left | yes | |
padding-right | yes | |
padding-top | yes | |
page | partial | Only for block-level and table elements, which are not inside
of a table and have an ancestor with the region property set to
body . |
page-break-after | yes | |
page-break-before | yes | |
page-break-inside | yes | |
pause | no | |
pause-after | no | |
pause-before | no | |
pitch | no | |
play-during | no | |
play-range | no | |
position | yes | |
quotes | yes | |
richness | no | |
right | yes | |
size | yes | |
speak | no | |
speak-header | no | |
speak-numeral | no | |
speak-punctuation | no | |
speech-rate | no | |
stress | no | |
table-layout | yes | |
text-align | yes | |
text-decoration | yes | |
text-indent | yes | |
text-transform | yes | |
top | yes | |
unicode-bibi | yes | |
vertical-align | yes | |
visibility | yes | |
voice-family | no | |
volume | no | |
white-space | yes | |
widows | yes | |
width | yes | |
word-spacing | yes | |
z-index | yes |
Extensions
The extension features of the tool mostly pertain to page-oriented
aspects. Care has been taken to not introduce new syntax. There are, however, a
number of new properties. Those are normally safely ignored by browsers. In the
case where there would be an impact on the layout produced by browsers, the
properties can be confined to the print
medium through @media rules.
Page Regions
This extension introduces XSL-FO-compatible page regions. Regions can
be defined by placing a region
property on an element. The allowed
values are bottom
, left
, right
,
top
and body
. At least one element with the
region
property set to body
should be present in the
document.The
XHTML User Agent style sheet sets this property to the body
element. Page sequences are only generated for the content of such an
element. The regions other than the body region must be the first direct
children of the body region. Otherwise they are ignored. In the case of
XHTML, for example, this means that they should come at the
beginning of the body
element.
On top of that, either the width
property, for left and
right regions, or the height
property, for top and bottom regions,
should be defined. They will determine the dimensions of the page
regions. The default value for width
is 20mm
. For
height
it is 10mm
.
The extension property precedence
is also available for
the top and bottom regions. Its value can be true
or
false
, the latter being the initial value. The property says
whether the width of the top or bottom region is equal to that of the page
reference area or if they give way to the left and right regions.
The regions work together with the @page rules, of which there should be
at least one. It is possible to specify different regions, which correspond to
the different page types in the style sheet. This can be achieved by also
specifying the page
property, which is a standard CSS2 property.
Consider the following example:
div.bottom-left, div.bottom-right { display: none; } @media print { div.bottom-left { height: 15mm; page: left; region: bottom; text-align: left; } div.bottom-right { height: 15mm; page: right; region: bottom; text-align: right; } span.page:before { content: counter(page); } }
This says that on left pages the bottom region is left-aligned, while
on right pages it is right-aligned. The span
element is used in
the following region definitions:
<div class="bottom-left"> <p> </p> <div><span class="page"/></div> </div> <div class="bottom-right"> <p> </p> <div><span class="page"/></div> </div>
The page
property bears a kind of inheritance mechanism.
For any page the regions with the most specific page
property will
be selected. A region without a page
property is the least
specific. A named page is more specific and the values left
and
right
are yet more specific. After this comes the new pseudo page
blank
, which is for blank pages that are generated because of page
positioning constraints such as left and right. The first page of a chapter,
for example, is sometimes forced to be a right page. This can produce an extra
blank page for the previous chapter. In fact, this maps directly to the XSL-FO
blank pages. There are special values, which are even more specific, such as
first-right
, blank-left
,
left-<page-name>
, etc. If, for example, there is no bottom
region for first-right
, but there is one for first
,
the latter will be selected if the first page happens to on the right. See
section page
for the
precise precedence rules.
In order for the top, bottom, left and right region elements not to
interfere with the normal flow it is best to set their display type to
none
.
Page Numbering
The two special counters page
and pages
in
this tool are taken over from the CSS3 Paged Media Module (see also [CSS3P]). The page
can be
used just like any other counter, except that it is confined to the regions.
The following example shows a document with a preface and a body. Each reset
the page count. The preface has a lower Roman numbering style, while the body
uses the decimal style. If the body page didn't reset the counter,
numbering would continue from the preface, but with a change of style.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <style type="text/css"> @page preface { counter-reset: page; margin: 10%; } @page body { counter-reset: page; margin: 10%; } div.bottom-preface { page: preface; region: bottom; } div.bottom-body { page: body; region: bottom; } div.bottom-preface > span.page:before { content: counter(page, lower-roman); } div.bottom-body > span.page:before { content: counter(page, decimal); } div.preface { page: preface; } div.body { page: body; } </style> </head> <body> <div class="bottom-preface"><span class="page"/></div> <div class="bottom-body"><span class="page"/></div> <div class="preface"> <p>Text.</p> </div> <div class="body"> <p>Text.</p> </div> </body> </html>
When switching between named pages you can control how the ending named
page sequence should be terminated with the extension property
force-page-count
. For example, it some page sequence produces five
pages, you can force the sequence to produce six pages by setting the property
to even
. An extra blank page will then be generated before starting
the new page sequence. If you don't want such behaviour, you should set the
property to no-force
, since the initial value is
auto
.
Page References
You sometimes want to write phrases like The diagram on page 19
...
. The CSSToXSLFO tool provides this functionality through the
page-ref
function, which can be used in the content
property. Its only parameter is the name of an attribute that contains the ID
of another element. The function call will be replaced with the number of the
page that element is on.
In XHTML it is a bit more complicated to achieve the desired result, because there aren't many extension attributes available for it. The following fragment shows how it can be done:
<img id="img1" src="file:///t.png"/> ... <span class="page-ref"><span class="img1"/></span>
The accompanying style sheet rule would then be:
span.page-ref > span:before { content: page-ref(class); }
Leaders
It is possible to use XSL-FO leaders through the display type
leader
. The properties defined in section 7.21 of [XSL-FO] (Leader and Rule Properties
) can be used in
a CSS style sheet, with the exception that the leader-length
property cannot have a length range as a value. If you want to create table of
contents lines or something similar, you also need the XSL-FO property
text-align-last
, described in section 7.15.10 of
[XSL-FO]. The following example shows how a table of
contents line could be made in XHTML.
<div class="toc"> <a href="#chapter1">Title of Chapter 1</a> <span class="leader"/> <span class="page-ref"><span class="chapter1"/></span> </div>
The piece of style sheet that goes with it is:
div.toc { text-align-last: justify; } span.leader { display: leader; leader-pattern: dots; leader-pattern-width: 5pt; } span.page-ref > span:before { content: page-ref(class); }
Named Strings
Named strings, as described in [CSS3G], are supported in CSSToXSLFO.
This consists of the string-set
property,
with which contents can be captured, and the string()
function.
The latter can occur in the value of the content
property. The
string-set
property accepts values which are similar to those of
the content
property. There is an additional keyword
contents
, which is replaced with the string value of the element
carrying the string-set
property.
The following is a simple XHTML example of how you can create a running header that refers to the current chapter.
<body> <div class="top"> <span class="mark"/> </div> ... <h1>Chapter Title</h1> ... </body>
Here is the bit of style sheet that does it:
div.top { region: top; display: none; } div.top > span.mark:before { content: string(mark); } h1 { string-set: mark contents; }
Hyphenation
Text can be hyphenated through the hyphenate
property,
which is inherited. The possible values are true
and
false
. Hyphenation is turned off by default.
Footnotes
It is possible to produce footnotes using the
footnote-reference
and footnote-body
display types.
The former is displayed in the flow, while
the latter goes to the footnote area at the bottom of the page. When a footnote
body occurs it must be either immediately preceded by a footnote reference or
have a :before
pseudo element with the display type
footnote-reference
. Otherwise
it is treated as if the display were none
. Whitespace between a
footnote reference and body is gobbled. A footnote reference can also occur on
its own.
The contents of both the footnote reference and body is free. Both
display types exist to give you complete control over the contents and style.
Usually some footnote counter is used, as shown in the example below. There is
an extra counter style footnote
, which produces symbols, such as
an asterix, dagger, etc.
h1 { counter-reset: footnote; } span.footnote-body { display: footnote-body; font-size: 0.83em; } span.footnote-body:before { content: counter(footnote); padding-right: 1em; } span.footnote-reference { display: footnote-reference; } span.footnote-reference:before { counter-increment: footnote; content: counter(footnote); font-size: 0.83em; vertical-align: super; }
In the document a footnote would then look like this:
<p>Paragraph text.<span class="footnote-reference"/><span class="footnote-body">Footnote text.</span></p>
You might find it cumbersome to have to place a footnote reference in
front of every footnote body. It can be avoided, at the expense of formatting
control however. You can define a :before
pseudo element for the
footnote body and give it the display type footnote-reference
.
Whatever contents it generates will then be used for the reference in the flow,
as well as in the footnote body at the bottom of the page. As a consequence,
the style is constrained by the fact that it must be decent for both contexts.
The style sheet becomes a bit simpler:
h1 { counter-reset: footnote; } span.footnote-body { display: footnote-body; font-size: 0.83em; } span.footnote-body:before { counter-increment: footnote; content: counter(footnote); display: footnote-reference; font-size: 0.83em; vertical-align: super; }
If you want full control over the formatting in both contexts and at the same time want to omit the footnote reference elements in the document, the solution is to pre-process the document. The transformation is rather trivial.
Orientation
You can rotate text with the orientation
property. This
works only for block, table and table cell elements. The possible values are 0,
90, 180, 270, -90, -180, -270. They represent the degrees in the
counter-clockwise direction. The initial value is 0.
List Style Types
The glyphs for the list-style-type
property, as defined in
[CSS3L], are implemented.
Multicolumn
With the properties column-count
, which must be strictly
positive, and column-gap
, which is a length, a multi-column layout
can be specified for a page. Both properties are allowed in an @page rule. As a
consequence, if you want to switch between column modes, you have to switch
pages as well.
With the column-span
property a blocks and tables, that
are not themselves inside of another table, can be made to span all the columns
of a multi-column page. The allowed values for the property are all
and none
.
Change Bars
The change bar properties introduced in
[XSL-FO11] are available for
:before
and :after
pseudo elements. For the latter,
only the change-bar-class
property is relevant.
The following is a simple example:
p.changed:before { change-bar-class: changed; change-bar-style: solid; /* initial value is none */ change-bar-width: 0.2pt; } p.changed:after { change-bar-class: changed; }
Note that this feature only works for XEP4 at the moment.
Links
The link
property can have the name of an attribute as
its value. The value of that attribute will be used for the generated link, as
the target URL or the internal target ID, if it is an
IDREF attribute, which distinguishes it from a relative
URL. Likewise, the value of the anchor
property can be the name
of an attribute, the value of which will become the target ID. This way an
internal link destination can be created. For example:
a[href] { link: href; } a[name] { anchor: name; }
Graphics
An external graphic can be included in a document through the display
type graphic
. The XSL-FO properties
content-height
, content-width
,
content-type
, scaling
and scaling-method
are supported. Their definition is in [XSL-FO]. The
property src
is interpreted differently. Its value should be the
name of an attribute that has a URI for a value. For the XHTML element
img
, for example, the User Agent style sheet contains the
following:
img { content-height: scale-to-fit; content-width: scale-to-fit; display: graphic; scaling: uniform; src: src; }
Column And Row Spanning
In XHTML one can specify column and row spanning with the
colspan
and rowspan
attributes on the td
and th
elements. It is, however, also possible to apply CSS to
other XML vocabularies. Hence, there should be an equivalent feature in CSS
to express this. The extension properties colspan
and
rowspan
serve that purpose. They can be used for elements with the
display type table-cell
.
Proportional Column Widths
Again in XHTML it is possible to say that a column should occupy a
relative portion of the total table width. It is done by setting the
width
attribute to a number, followed by an asterix. If we have,
for example, three columns with the widths 1*
, 2*
and 3*
,
they occupy 1, 2 and 3 sixth of the table width respectively. This is not part
of the HTML specification, but it is a widely supported feature.
In order to provide it for other XML vocabularies then XHTML, the
unit pcw
, which stands for proportional column width
, is
available for the width
property of an element with the display
type table-column
.
Repeating Table Headers And Footers
By default table headers and footers are repeated when a table spans
several pages. You can suppress this by setting the
table-omit-header-at-break
and
table-omit-footer-at-break
properties to true
respectively.
CSS3 Namespaces
Namespaces for selectors, as defined in [CSS3S], are implemented. This means you
can use namespace prefixes in element selectors and attribute conditions. The
prefixes are separated from the local name with a pipe sign (|
).
The namespaces are declared with the @namespace
rule, which
should always come right after the @import
rules if there are any.
In the following example the XHTML namespace has been declared as the default
namespace. Next to that, the DeltaXML namespace is declared with the prefix
dx
. You also see the use of the attr
function with an attribute
that has a prefix.
@namespace url(http://www.w3.org/1999/xhtml); @namespace dx url(http://www.deltaxml.com/ns/well-formed-delta-v1); *[dx|delta=add], dx|new { text-decoration: underline; } *[dx|delta=delete], dx|old { text-decoration: line-through; } p[dx|delta]:before { content: attr(dx|delta); display: marker; marker-offset: 0.5em; text-align: right; }
Wrappers
When processing XML in general you might encounter elements which represent pure structure, i.e. they are not directly related to layout. For such elements there shouldn't be any formatting objects in the output. Normally you would have to pre-process the document in order to get rid of them in the proper way.
The display type wrapper
is introduced to cope with common
cases. When an element has this display type, it will not contribute any
formatting objects. However, its inherited properties will be passed on to its
child elements, according to the property inheritance rules.
With respect to XML processing, a wrapper seems to be
transparant
. Note however that, while a wrapper can occur anywhere, it
influences CSS selector matching. For instance, it will interfere with
direct sibling
and direct child
selectors.
Foreign Elements
With the display type foreign
it is possible to transfer
part of a document unmodified to an fo:instream-foreign-object
element. This may be useful for elements that are in another namespace than
that of the document itself and which are supported by the XSL-FO processor.
Typical examples are SVG and MathML.
Property Specifications
anchor
Value: | <identifier> | attr(X) |
Initial: | none |
Applies to: | block-level and inline-level elements |
Inherited: | no |
Percentages: | N/A |
Media: |
- <identifier>
- The qualified name of an attribute, the value of which is the target ID. This type of value is deprecated, because it doesn't support namespace prefixes.
- attr(X)
- This returns the value of the attribute of the subject with the qualified name X. The CSS3 namespace prefixes are supported. The value is the target ID.
change-bar-class
Value: | <name> |
Initial: | none, value required |
Applies to: | before and after pseudo elements |
Inherited: | no |
Percentages: | N/A |
Media: |
- <name>
- An NCName, as defined in [NAMES], to allow pairing of before and after elements, which don't have to belong to the same element. This way a change bar context is created.
change-bar-color
Value: | <color> |
Initial: | the value of the color property |
Applies to: | before pseudo elements |
Inherited: | no |
Percentages: | N/A |
Media: |
- <color>
- Specifies the color of the change bar.
change-bar-offset
Value: | <length> |
Initial: | 6pt |
Applies to: | before pseudo elements |
Inherited: | no |
Percentages: | N/A |
Media: |
- <length>
- Gives the distance from the edge of the column area containing the
text that is marked as changed to the center of the generated change bar. A
positive distance is directed away from the column region and into the margin
regardless of the
change-bar-placement
property. Relative lengths (i.e., percentage values and lengths with units ofem
) are not permitted for the value of this property.
change-bar-placement
Value: | left | right | inside | outside | alternate |
Initial: | start |
Applies to: | before pseudo elements |
Inherited: | no |
Percentages: | N/A |
Media: |
- alternate
- When there are exactly two columns, the change bar will be offset
from the left edge of all column one areas and the right edge of all column two
areas; when there are any other number of columns, this value is equivalent to
outside
. - inside
- If the page binding edge is on the left-edge, the change bar will be offset from the left edge of all column areas. If the binding is the right-edge, the change bar will be offset from the right edge of all column areas. If the page binding edge is on neither the left-edge nor right-edge, the change bar will be offset from the left edge of all column areas.
- left
- The change bar will be offset from the left edge of all column areas.
- outside
- If the page binding edge is on the left-edge, the change bar will be offset from the right edge of all column areas. If the binding is the right-edge, the change bar will be offset from the left edge of all column areas. If the page binding edge is on neither the left-edge nor right-edge, the change bar will be offset from the right edge of all column areas.
- right
- The change bar will be offset from the right edge of all column areas.
change-bar-style
Value: | <border-style> |
Initial: | none |
Applies to: | before pseudo elements |
Inherited: | no |
Percentages: | N/A |
Media: |
change-bar-width
Value: | <border-width> |
Initial: | medium |
Applies to: | before pseudo elements |
Inherited: | no |
Percentages: | N/A |
Media: |
- <border-width>
- Relative lengths (i.e., percentage values and lengths with units of
em
) are not permitted for the value of this property.
colspan
Value: | <integer> |
Initial: | 1 |
Applies to: | table cells |
Inherited: | no |
Percentages: | N/A |
Media: |
- <integer>
- Expresses the number of columns the table cell will span. The value must be larger than or equal to 1.
column-count
Value: | <integer> |
Initial: | 1 |
Applies to: | the page context |
Inherited: | no |
Percentages: | N/A |
Media: |
- <integer>
- The value must be larger than or equal to 1.
column-gap
Value: | <length> | <percentage> |
Initial: | 12.0pt |
Applies to: | the page context |
Inherited: | no |
Percentages: | refer to the width of the body region |
Media: |
- <length>
- This is an unsigned length, If a negative value has been specified a value of 0pt will be used.
- <percentage>
- The value is a percentage of the width of the body region.
column-span
Value: | none | all |
Initial: | none |
Applies to: | block elements which are not in table elements |
Inherited: | no |
Percentages: | N/A |
Media: |
- all
- This element spans all columns of a multi-column region.
- none
- This element does not span multiple columns of a multi-column region.
content-height
Value: | auto | scale-to-fit | <length> | <percentage> |
Initial: | auto |
Applies to: | graphic elements |
Inherited: | no |
Percentages: | intrinsic height |
Media: |
- auto
- The content-height should be the intrinsic content-height.
- scale-to-fit
- A size of the content-height equal to the height of the viewport. This implies a certain scaling factor to be applied onto the content.
- <length>
- An absolute size for the content-height. This implies a certain scaling factor to be applied onto the content.
- <percentage>
- A percentage representing a scaling factor applied to the intrinsic height.
content-type
Value: | auto | <string> |
Initial: | auto |
Applies to: | graphic elements |
Inherited: | no |
Percentages: | intrinsic height |
Media: |
- auto
- No identification of the content-type. The User Agent may determine
it by
sniffing
or by other means. - <string>
- A specification of the content-type in terms of a mime-type, which
has the form
content-type:
followed by a mime content-type, e.g., content-type="content-type:image/svg+xml".
content-width
Value: | auto | scale-to-fit | <length> | <percentage> |
Initial: | auto |
Applies to: | graphic elements |
Inherited: | no |
Percentages: | intrinsic width |
Media: |
- auto
- The content-width should be the intrinsic content-width.
- scale-to-fit
- A size of the content-width equal to the width of the viewport. This implies a certain scaling factor to be applied onto the content.
- <length>
- An absolute size for the content-width. This implies a certain scaling factor to be applied onto the content.
- <percentage>
- A percentage representing a scaling factor applied to the intrinsic width.
display
This section specifies additional values for the property.
Value: | footnote-body | footnote-reference | foreign | graphic | leader | wrapper |
Initial: | inline |
Applies to: | all elements |
Inherited: | no |
Percentages: | N/A |
Media: |
- footnote-body
- The contents of the element goes to the footnote area. The element
must be either immediately preceded by an element of type
footnote-reference
or have a:before
pseudo element of that type. Otherwise it is treated as if its display type werenone
. Whitespace between a footnote reference and body is removed. In case a pseudo element is used, the contents it generates is displayed in the flow, as well as in the footnote body. - footnote-reference
- This is an inline variant. Its contents is displayed in the flow. It
can occur without a following
footnote-body
element. - foreign
- If an element has this display type, it is placed unmodified in an
fo:instream-foreign-object
element. - graphic
- This display type is used to include external graphics.
- leader
- This display type is used to produce XSL-FO leaders.
- wrapper
- An element with this display type doesn't contribute any formatting objects. Its inherited properties are nevertheless inherited by its subtree.
force-page-count
Value: | auto | even | odd | end-on-even | end-on-odd | no-force |
Initial: | auto |
Applies to: | the page context |
Inherited: | no |
Percentages: | N/A |
Media: |
The property is used to impose a constraint on the number of pages
in a page sequence. In the event that this constraint is not satisfied, an
additional page will be added to the end of the sequence. This page becomes the
last
page of that sequence.
- auto
- Force the last page in this page sequence to be an odd page if the
initial page number of the next page sequence is even. Force it to be an even
page if the initial page number of the next page sequence is odd. If there is
no next page sequence or if the value of its initial page number is
auto
do not force any page. - even
- Force an even number of pages in this page sequence.
- odd
- Force an odd number of pages in this page sequence.
- end-on-even
- Force the last page in this page sequence to be an even page.
- end-on-odd
- Force the last page in this page sequence to be an odd page.
- no-force
- Do not force either an even or an odd number of pages in this page sequence.
hyphenate
Value: | false | true |
Initial: | false |
Applies to: | block-level and inline-level elements |
Inherited: | yes |
Percentages: | N/A |
Media: |
- false
- Hyphenation is not active for the text in this element.
- true
- Hyphenation is active for the text in this element.
leader-alignment
Value: | none | reference-area | page |
Initial: | none |
Applies to: | leader elements |
Inherited: | yes |
Percentages: | N/A |
Media: |
Specifies whether leader elements having identical content and property
values shall have their patterns aligned with each other, with respect to their
common reference-area or page. For leader elements where the
leader-pattern
property is specified as dots
or as
use-content
, this property will be honored. If the leader elements
is aligned, the left-edge of each cycle of the repeated pattern will be placed
on the left-edge of the next cycle in the appropriate pattern-alignment
grid.
- none
- Leader-pattern has no special alignment.
- page
- Leader-pattern is aligned as if it began on the current page's left-edge.
- reference-area
- Leader-pattern is aligned as if it began on the current reference-area's content-rectangle left-edge.
leader-length
Value: | <length> | <percentage> |
Initial: | 12.0pt |
Applies to: | leader elements |
Inherited: | yes |
Percentages: | refer to the width of the content-rectangle of the parent area. |
Media: |
- <length>
- Sets the length of a leader element.
- <percentage>
- Sets the length of a leader element to a percentage of the width of the content-rectangle of the parent area.
leader-pattern
Value: | space | rule | dots | use-content |
Initial: | space |
Applies to: | leader elements |
Inherited: | yes |
Percentages: | N/A |
Media: |
- dots
- Leader is to be filled with a repeating sequence of dots. The choice of dot character is dependent on the user agent.
- rule
- Leader is to be filled with a rule. If this choice is selected, the
rule-thickness
andrule-style
properties are used to set the leader's style. - space
- Leader is to be filled with blank space.
- use-content
- Leader is to be filled with a repeating pattern as specified by the children of the leader element.
leader-pattern-width
Value: | use-font-metrics | <length> | <percentage> |
Initial: | use-font-metrics |
Applies to: | leader elements |
Inherited: | yes |
Percentages: | refer to the width of the content-rectangle of the parent area. |
Media: |
- use-font-metrics
- Use the width of the leader-pattern as determined from its font metrics.
- <length>
- Sets the length for leader-pattern-repeating. The leader will have an
inline-space inserted after each pattern cycle to account for any difference
between the width of the pattern as determined by the font metrics and the
width specified in this property. If the length specified is less than the
value that would be determined via the
use-font-metrics
choice, the value of this property is computed as ifuse-font-metrics
choice had been specified. - <percentage>
- Sets the length for leader-pattern-repeating to a percentage of the width of the content-rectangle of the parent area.
For leader elements where the
leader-pattern
property is specified as dots
or as
use-content
, this property will be honored.
link
Value: | <identifier> | attr(X) |
Initial: | none |
Applies to: | block-level and inline-level elements |
Inherited: | no |
Percentages: | N/A |
Media: |
- <identifier>
- The qualified name of an attribute, the value of which is either a target ID or a URI. It is considered as an ID if the attribute is of type IDREF. This way a distinction is made with a relative URL. Note that the attribute type information should be available. This requires a document type definition. This type of value is deprecated, because it doesn't support namespace prefixes.
- attr(X)
- This returns the value of the attribute of the subject with the qualified name X. The CSS3 namespace prefixes are supported. The value is considered as an ID if the attribute is of type IDREF. This way a distinction is made with a relative URL. Note that the attribute type information should be available. This requires a document type definition.
list-style-type
This section specifies additional glyph values for the property.
Value: | box | check | diamond | hyphen |
Initial: | disc |
Applies to: | elements with display: list-item |
Inherited: | yes |
Percentages: | N/A |
Media: |
- box
- A hollow square.
- check
- A check mark.
- diamond
- A filled diamond.
- hyphen
- A hyphen bullet.
orientation
Value: | 0 | 90 | 180 | 270 | -90 | -180 | -270 |
Initial: | 0 |
Applies to: | block, table and table cell elements |
Inherited: | yes |
Percentages: | N/A |
Media: |
- 0
- The material in this element is not rotated.
- 90
- The material in this element is rotated 90 degrees counter-clockwise with respect to the containing block element.
- 180
- The material in this element is rotated 180 degrees counter-clockwise with respect to the containing block element.
- 270
- The material in this element is rotated 270 degrees counter-clockwise with respect to the containing block element.
- -90
- The material in this element is rotated 90 degrees clockwise with respect to the containing block element.
- -180
- The material in this element is rotated 180 degrees clockwise with respect to the containing block element.
- -270
- The material in this element is rotated 270 degrees clockwise with respect to the containing block element.
page
This section specifies the property in the context of static regions. It defines the pages to which the static region applies. If more than one static region of the same kind (left, right, top or bottom) applies to a page, the most specific is selected, i.e. the one for which the most conditions are fulfilled. Each property value expresses a number of conditions.
Value: | auto | first | left | right | blank | first-left | first-right | blank-left | blank-right | first-<identifier> | left-<identifier> | right-<identifier> | blank-<identifier> | first-left-<identifier> | first-right-<identifier> | blank-left-<identifier> | blank-right-<identifier> | <identifier> |
Initial: | auto |
Applies to: | static regions |
Inherited: | no |
Percentages: | N/A |
Media: |
- auto
- Applies to any page.
- blank
- Applies if the page is a blank page. Blank pages can be generated, for example, when page breaks are forced to left or right pages.
- blank-left
- Applies if the page is a blank and a left page.
- blank-right
- Applies if the page is a blank and a right page.
- blank-<identifier>
- Applies if the page is a blank and a named page, with the name set to the specified identifier.
- blank-left-<identifier>
- Applies if the page is a blank, left and named page, with the name set to the specified identifier.
- blank-right-<identifier>
- Applies if the page is a blank, right and named page, with the name set to the specified identifier.
- first
- Applies if the page is a first page.
- first-left
- Applies if the page is a first and a left page.
- first-right
- Applies if the page is a first and a right page.
- first-<identifier>
- Applies if the page is a first and a named page, with the name
set to the specified identifier. When the document switches to a named page
sequence, using the
page
property in the regular way, the first page of that sequence is a first page. - first-left-<identifier>
- Applies if the page is a first, left and named page, with the name set to the specified identifier.
- first-right-<identifier>
- Applies if the page is a first, right and named page, with the name set to the specified identifier.
- left
- Applies if the page is a left page.
- left-<identifier>
- Applies if the page is a left and a named page, with the name set to the specified identifier.
- right
- Applies if the page is a right page.
- right-<identifier>
- Applies if the page is a right and a named page, with the name set to the specified identifier.
- <identifier>
- Applies if the page is a named page, with the name set to the specified identifier.
precedence
Value: | false | true |
Initial: | false |
Applies to: | static top and bottom regions |
Inherited: | no |
Percentages: | N/A |
Media: |
- false
- The width of the region is reduced by the incursions of the left and right regions.
- true
- The height of the left and right regions is reduced by the incursions of this region.
region
Value: | body | left | right | top | bottom | none |
Initial: | none |
Applies to: | all elements, but see prose |
Inherited: | no |
Percentages: | N/A |
Media: |
- body
- There should be one element with this value for the property. For the contents of this element the page sequences will be generated.
- bottom
- This element becomes the bottom static region. The pages for which
this is the case can be limited through the
page
property. - left
- This element becomes the left static region.
- none
- The element is not a region.
- right
- This element becomes the right static region.
- top
- This element becomes the top static region.
The static region elements should be the first child elements of the
body region. In other words, they should precede all elements which are not
static regions, otherwise their region
property is ignored. The
property is also ignored if there are no @page rules. In that case the default
page set-up is generated.
rowspan
Value: | <integer> |
Initial: | 1 |
Applies to: | table cells |
Inherited: | no |
Percentages: | N/A |
Media: |
- <integer>
- Expresses the number of rows the table cell will span. The value must be larger than or equal to 1.
rule-style
This property applies only if the leader-pattern
property is
specified as rule
.
Value: | none | dotted | dashed | solid | double | groove | ridge |
Initial: | solid |
Applies to: | leader elements |
Inherited: | yes |
Percentages: | N/A |
Media: |
- dashed
- The rule is a series of short line segments.
- dotted
- The rule is a series of dots.
- double
- The rule is two solid lines. The sum of the two lines and the space
between them equals the value of the
rule-thickness
property. - groove
- The rule looks as though it were carved into the canvas. (Top/left half of the rule's thickness is the color specified; the other half is white.)
- none
- No rule, forces
rule-thickness
to 0. - ridge
- The opposite of
groove
, the rule looks as though it were coming out of the canvas. (Bottom/right half of the rule's thickness is the color specified; the other half is white.) - solid
- The rule is a single line segment.
rule-thickness
This property applies only if the leader-pattern
property is
specified as rule
.
Value: | <length> |
Initial: | 1.0pt |
Applies to: | leader elements |
Inherited: | yes |
Percentages: | N/A |
Media: |
- <length>
- The rule-thickness is always perpendicular to its length-axis. The rule is thickened equally above and below the line's alignment position.
scaling
Value: | uniform | non-uniform |
Initial: | uniform |
Applies to: | graphic elements |
Inherited: | no |
Percentages: | intrinsic width |
Media: |
- non-uniform
- Scaling need not preserve the intrinsic aspect ratio.
- uniform
- Scaling should preserve the intrinsic aspect ratio.
scaling-method
Value: | auto | integer-pixels | resample-any-method |
Initial: | auto |
Applies to: | graphic elements |
Inherited: | no |
Percentages: | intrinsic width |
Media: |
- auto
- The User Agent is free to choose either resampling, integer scaling, or any other scaling method.
- integer-pixels
- The User Agent should scale the image such that each pixel in the original image is scaled to the nearest integer number of device-pixels that yields an image less-then-or-equal-to the image size derived from the content-height, content-width, and scaling properties.
- resample-any-method
- The User Agent should resample the supplied image to provide an image
that fills the size derived from the
content-height
,content-width
, andscaling
properties. The user agent may use any sampling method.
src
Value: | <identifier> | attr(X) |
Initial: | none, value required |
Applies to: | graphic elements |
Inherited: | no |
Percentages: | N/A |
Media: |
- <identifier>
- The qualified name of an attribute, the value of which is a URI. This type of value is deprecated, because it doesn't support namespace prefixes.
- attr(X)
- This returns the value of the attribute of the subject with the qualified name X. The CSS3 namespace prefixes are supported. The value is a URI.
string-set
Value: | none | <identifier> contents | <identifier> <content> |
Initial: | none |
Applies to: | all elements |
Inherited: | no |
Percentages: | N/A |
Media: |
- none
- No named string is set.
- <identifier> contents
- The string named by the identifier is set to the textual contents of the element.
- <identifier> <content>
- The string named by the identifier is set to the result of the
evaluation of the expression in <content>. The syntax for the expression is
the same as that for the
content
property.
text-align-last
Value: | <identifier> |
Initial: | relative |
Applies to: | block elements |
Inherited: | no |
Percentages: | N/A |
Media: |
- center
- Specifies that the contents is to be centered horizontally.
- inside
- If the page binding edge is on the left-edge, the alignment will be left. If the binding is on the right-edge, the alignment will be right. If neither, use left alignment.
- justify
- Specifies that the contents is to be expanded to fill the available width.
- left
- Specifies that the contents is to be aligned on the left-edge.
- outside
- If the page binding edge is on the left-edge, the alignment will be right. If the binding is on the right-edge, the alignment will be left. If neither, use right alignment.
- relative
- If
text-align
isjustify
, then the alignment of the last line, and of any line ending in U+000A, will be left. Iftext-align
is notjustify
,text-align-last
will use the value oftext-align
. - right
- Specifies that the contents is to be aligned on the right-edge.
table-omit-footer-at-break
Value: | false | true |
Initial: | false |
Applies to: | tables |
Inherited: | no |
Percentages: | N/A |
Media: |
- false
- This property specifies that the footer should not be ommitted.
- true
- This property specifies that the footer should be ommitted.
table-omit-header-at-break
Value: | false | true |
Initial: | false |
Applies to: | tables |
Inherited: | no |
Percentages: | N/A |
Media: |
- false
- This property specifies that the header should not be ommitted.
- true
- This property specifies that the header should be ommitted.
Miscellaneous Specifications
The :blank Pseudo-class
The :blank pseudo-class is available to specify properties in the page context for blank pages. Those can be generated, for example, when pages are forced to start at the left or right.
The page And pages Counters
The page counter represents the current page number, while the pages counter represents the total number of pages in the document. Both can be used in static regions only. The page counter may be reset in the page context.
The page-ref Function
The page-ref function can be used in the content
property. Its only parameter is either the qualified name of an attribute that
contains the ID of another element, or the attr(X) function, where X is the
qualified name of such an attribute. The former is deprecated, because it
doesn't support CSS3 namespace prefixes, while the latter does. The function
call will be replaced with the number of the page the target element is on.
The string Function
The string function produces the string that was saved with a
string-set
property. Its argument is the name used in a
string-set
property. If a named string is set more than once on a
page, the first occurrence will be returned by the string function.
The footnote Counter Style
This counter style produces symbols in the following order: *, †, ‡, §, ||, ¶, #, **, ††, ‡‡, §§. If the counter value if larger than the number of symbols in the preceding list, the * symbol is generated.
The pcw Unit
This unit is available for the width
property of an element
with display type table-column
. It expresses the proportional width
for a table column. The value should be divided by the sum of all the present
proportional widths, which itself is equal to the width of the table minus all
fixed column widths.
The @namespace Rule
With the @namespace rule a namespace can be declared, with or without a prefix. In the latter case it is the default namespace. The scope of a declared namespace is limited to the style sheet entity in which it is declared. The @namespace rule should come right after the @import rules if there are any and before all other rules. An @namespace rule has an optional prefix argument, which is an identifier, followed by a mandatory URI specification. Consult [CSS3S] to learn how namespaces work with selectors.
Embedding In An Application
API Specification
be.re.css.CSSToXSLFOFilter
This class extends org.xml.sax.helpers.XMLFilterImpl. The source of the SAX events that are sent through the filter must be namespace aware. If it is an XML parser this option must be turned on.
Constructors
- baseUrl
-
The
baseUrl
is used to resolve relative URLs. This includes references to style sheets as well as other resources. Because of the latter the resulting XSL-FO document is not relocatable. The relative URLs in the input document are transformed into absolute ones using thebaseUrl
. This copes with the case where the input document is an anonymous stream that refers to style sheets in a relative way. The set of style sheets is then relocatable through thebaseUrl
.If
baseUrl
isnull
no resolution of relative URLs will be done. - userAgentStyleSheet
- The default style sheet for the filter. It is used in the way
described in section 6.4 of [CSS2]. If the parameter is
null
, a default style sheet for XHTML is used. - userAgentParameters
- These are defined in section
User Agent Parameters
. - parent
- The parent filter. It must not be
null
. - debug
- If
debug
istrue
a number of debug files are dumped. They show the results of the internal processing steps.
Constructs the filter with debug
set to
false
.
Constructs the filter with an empty userAgentParameters
map
and debug
set to false
.
Constructs the filter with userAgentStyleSheet
set to
null
, an empty userAgentParameters
map
and debug
set to false
.
Constructs the filter with baseUrl
and
userAgentStyleSheet
set to
null
, an empty userAgentParameters
map
and debug
set to false
.
Constructs the filter without a parent.
Constructs the filter without a parent and debug
set to
false
.
Constructs the filter without a parent, an empty
userAgentParameters
map and debug
set to
false
.
Constructs the filter without a parent, userAgentStyleSheet
set to null
, an empty userAgentParameters
map and
debug
set to false
.
Constructs the filter without a parent, baseUrl
and
userAgentStyleSheet
set to null
, an empty
userAgentParameters
map and debug
set to
false
.
Methods
Returns the base URL of the filter. It is either set in a constructor
or with the setBaseUrl
method.
Returns the User Agent parameters of the filter. They are either set in
a constructor or with the setUserAgentStyleSheet
method.
Returns the User Agent style sheet of the filter. It is either set in a
constructor or with the setUserAgentStyleSheet
method.
Sets the base URL of the filter. The base URL is used to resolve
relative URLs in the input document. See also baseUrl
.
Sets the User Agent parameters of the filter. See also userAgentParameters
.
Sets the User Agent style sheet of the filter. See also userAgentStyleSheet
.
be.re.css.CSSToXSLFOException
This class extends java.lang.Exception.
Constructors
This is just a wrapper around e
.
The parameter will be returned by the method getMessage
.
be.re.css.CSSToXSLFO
This class contains a few convenience methods with which an XML filter set-up can be avoided, because they do it for you.
Methods
- in
- The input document. It must not be
null
. - out
- The output document. It must not be
null
. - baseUrl
- See
baseUrl
. - userAgentStyleSheet
- See
userAgentStyleSheet
. - catalog
- The catalog used to resolve entities during XML parsing. It must
have the format defined by SGML Open Technical
Resolution TR9401:1997. Only the
PUBLIC
andSYSTEM
keywords are supported. It may benull
. - userAgentParameters
- See
userAgentParameters
. - preprocessors
- An array of XSLT style sheets. The input goes through them in the
specified order and before the
CSSToXSLFOFilter
. - validate
- Turns on validation during XML parsing of the input document.
- debug
- See
debug
.
Calls the first variant of convert
with
baseUrl
, catalog
and preprocessors
set
to null
, validate
and debug
set to false
and an empty userAgentParameters
map.
Calls the first variant of convert
with
baseUrl
, userAgentStyleSheet
, catalog
and
preprocessors
set to null
, validate
and
debug
set to false and an empty userAgentParameters
map.
Examples
Since CSSToXSLFOFilter is derived from org.xml.sax.helpers.XMLFilterImpl., it implements all SAX event interfaces, as well as org.xml.sax.XMLFilter. As a consequence, the filter can occur in input and output filter chains.
Example 1
The most straight-forward scenario is an application that reads the input document from a file and that writes an XSL-FO document into another file. For this we need an XML parser that can produce SAX events. The parser implements the org.xml.sax.XMLReader interface, so we can make it the parent of CSSToXSLFOFilter.
In order to create a parser, we first have to set up the parser factory and make it namespace-aware. This happens at the lines 6 through 8. The filter can now be created with the input document as the base URL (in case any relative URLs need to be resolved) and an XML parser as its parent. This is done at the lines 9 through 14.
We now have to prepare the output part. We use an XSLT transformer without a style sheet to copy the SAX events to the output. The transformer must be in a form that accepts SAX events. This is why a javax.xml.transform.sax.TransformerHandler is created at lines 15 through 19. It implements the org.xml.sax.ContentHandler interface. By giving it the output file as a result (lines 20 through 26), the SAX events are transformed in the XML syntax.
The input and output parts can now be connected by setting the content
handler of the filter to the transformer handler (line 27). The whole chain is
then activated by calling the parse
method, passing it the input
document in the form of a file. The filter will pass this call onto the parser,
which is its parent. The parser starts producing SAX events that go through
the filter and into the transformer handler.
1 public class Example1 2 { 3 public static void 4 main(String[] args) throws Exception 5 { 6 javax.xml.parsers.SAXParserFactory factory = 7 javax.xml.parsers.SAXParserFactory.newInstance(); 8 factory.setNamespaceAware(true); 9 be.re.css.CSSToXSLFOFilter filter = 10 new be.re.css.CSSToXSLFOFilter 11 ( 12 new java.io.File(args[0]).toURL(), // base URL. 13 factory.newSAXParser().getXMLReader() 14 ); 15 javax.xml.transform.sax.TransformerHandler handler = 16 ( 17 (javax.xml.transform.sax.SAXTransformerFactory) 18 javax.xml.transform.TransformerFactory.newInstance() 19 ).newTransformerHandler(); 20 handler.setResult 21 ( 22 new javax.xml.transform.stream.StreamResult 23 ( 24 new java.io.File(args[1]) 25 ) 26 ); 27 filter.setContentHandler(handler); 28 filter.parse 29 ( 30 new org.xml.sax.InputSource 31 ( 32 new java.io.FileInputStream(args[0]) 33 ) 34 ); 35 } 36 }
Example 2
A variation of the previous example is to perform the transformation of the SAX events coming out of the filter to XML syntax in another way. In the previous example the parser had the control flow and the transformer acted as a handler of SAX events. We can also give the control flow to a transformer that reads the input and copies it to the output, because we don't give it any style sheet. We need to create a javax.xml.transform.Transformer. It is done at lines 15 through 17. The actual transformation is launched at lines 18 through 32. For this to work, we have to wrap our filter in a javax.xml.transform.sax.SAXSource. For the transformer it is as if it is going to call an XML parser.
1 public class Example2 2 { 3 public static void 4 main(String[] args) throws Exception 5 { 6 javax.xml.parsers.SAXParserFactory factory = 7 javax.xml.parsers.SAXParserFactory.newInstance(); 8 factory.setNamespaceAware(true); 9 be.re.css.CSSToXSLFOFilter filter = 10 new be.re.css.CSSToXSLFOFilter 11 ( 12 new java.io.File(args[0]).toURL(), // base URL. 13 factory.newSAXParser().getXMLReader() 14 ); 15 javax.xml.transform.Transformer transformer = 16 javax.xml.transform.TransformerFactory.newInstance(). 17 newTransformer(); 18 transformer.transform 19 ( 20 new javax.xml.transform.sax.SAXSource 21 ( 22 filter, // Acts as the XMLReader. 23 new org.xml.sax.InputSource 24 ( 25 new java.io.FileInputStream(args[0]) 26 ) 27 ), 28 new javax.xml.transform.stream.StreamResult 29 ( 30 new java.io.File(args[1]) 31 ) 32 ); 33 } 34 }
Example 3
This example shows how a pre-processing step can be added to the filter chain. The input document is transformed by the pre-processor and the resulting SAX events go through the conversion filter. The pre-processor is created at lines 9 through 13. This one does nothing, i.e. it lets the events go through unmodified. In reality you would replace it with a class of your own.
The pre-processor instead of the filter is now initialised with the
XML parser as its parent. The pre-processor will become the parent of the
filter, as shown at line 18. When the parse
method is called, the
filter passes the call onto the pre-processor, which in turn passes it onto the
parser. The SAX events produced by the parser will then flow through the
pre-processor, which in turn forwards them, possibly modified, to the
filter.
1 public class Example3 2 { 3 public static void 4 main(String[] args) throws Exception 5 { 6 javax.xml.parsers.SAXParserFactory factory = 7 javax.xml.parsers.SAXParserFactory.newInstance(); 8 factory.setNamespaceAware(true); 9 org.xml.sax.helpers.XMLFilterImpl myPreprocessor = 10 new org.xml.sax.helpers.XMLFilterImpl 11 ( 12 factory.newSAXParser().getXMLReader() 13 ); 14 be.re.css.CSSToXSLFOFilter filter = 15 new be.re.css.CSSToXSLFOFilter 16 ( 17 new java.io.File(args[0]).toURL(), // base URL. 18 myPreprocessor 19 ); 20 javax.xml.transform.sax.TransformerHandler handler = 21 ( 22 (javax.xml.transform.sax.SAXTransformerFactory) 23 javax.xml.transform.TransformerFactory.newInstance() 24 ).newTransformerHandler(); 25 handler.setResult 26 ( 27 new javax.xml.transform.stream.StreamResult 28 ( 29 new java.io.File(args[1]) 30 ) 31 ); 32 filter.setContentHandler(handler); 33 filter.parse 34 ( 35 new org.xml.sax.InputSource 36 ( 37 new java.io.FileInputStream(args[0]) 38 ) 39 ); 40 } 41 }
Example 4
The previous example can be modified in such a way that the pre-processor is an XSLT style sheet. From this style sheet a org.xml.sax.XMLFilter must be made, because it will sit between the XML parser and the filter. This is shown at lines 9 through 19. The transformer factory is re-used afterwards to create also the output handler.
1 public class Example4 2 { 3 public static void 4 main(String[] args) throws Exception 5 { 6 javax.xml.parsers.SAXParserFactory factory = 7 javax.xml.parsers.SAXParserFactory.newInstance(); 8 factory.setNamespaceAware(true); 9 javax.xml.transform.sax.SAXTransformerFactory trFactory = 10 (javax.xml.transform.sax.SAXTransformerFactory) 11 javax.xml.transform.TransformerFactory.newInstance(); 12 org.xml.sax.XMLFilter myPreprocessor = 13 trFactory.newXMLFilter 14 ( 15 new javax.xml.transform.stream.StreamSource 16 ( 17 new java.io.File(args[2]) 18 ) 19 ); 20 myPreprocessor.setParent 21 ( 22 factory.newSAXParser().getXMLReader() 23 ); 24 be.re.css.CSSToXSLFOFilter filter = 25 new be.re.css.CSSToXSLFOFilter 26 ( 27 new java.io.File(args[0]).toURL(), // base URL. 28 myPreprocessor 29 ); 30 javax.xml.transform.sax.TransformerHandler handler = 31 trFactory.newTransformerHandler(); 32 handler.setResult 33 ( 34 new javax.xml.transform.stream.StreamResult 35 ( 36 new java.io.File(args[1]) 37 ) 38 ); 39 filter.setContentHandler(handler); 40 filter.parse 41 ( 42 new org.xml.sax.InputSource 43 ( 44 new java.io.FileInputStream(args[0]) 45 ) 46 ); 47 } 48 }
Example 5
In all previous examples we have been parsing an input document. In some
applications, however, the data might come from somewhere else. It is possible,
for example, to synthesize the XML from data that resides in the database. In
such a scenario our filter no longer has a parent but becomes the SAX event
handler of some system method, generateReport
in this example.Note
that a real system method would probably need more than just the filter to do
its work. It would therefore have more parameters.
This system method has the control flow. It fetches the data and generates the
SAX events. In the case the generated XML stream is not suitable for CSS
conversion, a pre-processor may be specified as the parent of the filter.
1 public class Example5 2 { 3 public static void 4 main(String[] args) throws Exception 5 { 6 be.re.css.CSSToXSLFOFilter filter = 7 new be.re.css.CSSToXSLFOFilter(); 8 javax.xml.transform.sax.TransformerHandler handler = 9 ( 10 (javax.xml.transform.sax.SAXTransformerFactory) 11 javax.xml.transform.TransformerFactory.newInstance() 12 ).newTransformerHandler(); 13 handler.setResult 14 ( 15 new javax.xml.transform.stream.StreamResult 16 ( 17 new java.io.File(args[0]) 18 ) 19 ); 20 filter.setContentHandler(handler); 21 generateReport(filter); 22 } 23 private static void 24 generateReport(org.xml.sax.ContentHandler handler) 25 { 26 } 27 }
Example 6
It may be the case that you want to synthesize the XML stream in a system method, which needs the control flow, but that the interface of your XSL-FO formatter is such that it also needs the control flow. In other words, the formatter is not available in the form of a SAX event handler, but has some method that must be called to perform the actual formatting. At lines 21 through 31 there a hypothetical example of such a formatter.
To solve this control flow conflict you can create an adapter that
implements the org.xml.sax.XMLReader
interface. Instead of actually parsing some XML you let both
parse
methods call your system method. The parameters the latter
needs are passed through the constructor of the adapter. When the formatter now
calls the parse
method it really ends up calling the system
method, which synthesizes the SAX events.
1 public class Example6 2 { 3 public static void 4 main(String[] args) throws Exception 5 { 6 be.re.css.CSSToXSLFOFilter filter = 7 new be.re.css.CSSToXSLFOFilter 8 ( 9 new MyReportGenerator(new Object()) 10 ); 11 MyXSLFOFormatter myFormatter = new MyXSLFOFormatter(); 12 myFormatter.format 13 ( 14 new javax.xml.transform.sax.SAXSource(filter, null), 15 new java.io.FileOutputStream(args[0])); 16 } 17 private static void 18 generateReport(Object context) 19 { 20 } 21 public static class MyXSLFOFormatter 22 { 23 public void 24 format 25 ( 26 javax.xml.transform.Source source, 27 java.io.OutputStream out 28 ) 29 { 30 } 31 } 32 public static class MyReportGenerator 33 extends org.xml.sax.helpers.XMLFilterImpl 34 { 35 private Object context; 36 public 37 MyReportGenerator(Object context) 38 { 39 this.context = context; 40 } 41 public void 42 parse(org.xml.sax.InputSource input) 43 throws org.xml.sax.SAXException, java.io.IOException 44 { 45 generateReport(context); 46 } 47 public void 48 parse(String systemId) 49 throws org.xml.sax.SAXException, java.io.IOException 50 { 51 generateReport(context); 52 } 53 } 54 }
Some Techniques
A few practical cases of formatting contructs, which are either more
advanced or not yet very common, are described in this chapter. Gradually, new
cases will be added. The chapter is some sort of how to
section in the
user guide. The examples use XHTML as the input document language.
Customising List Labels With Markers
The genaration of the labels of an itemised list is somewhat fixed. It
depends on the value of the list-style-type
property.The
list-style-image
and list-style-position
properties
are not supported by this tool. Sometimes, however, more control is
required over how the labels look like. This can be achieved through
markers.
Basically, you have to specify a :before
pseudo element
with the display type marker
in your style sheet for those
elements you have given the display type list-item
. Strictly
speaking that display type is not needed, but if you are about to convert your
existing lists, those elements would have that display type.
In the pseudo element you have control over the formatting of the label.
The only exception is that the width
property must be fixed. The
tool doesn't support the automatic calculation of the required width. If your
style sheet doesn't specify a width, a default value will be used. In order to
not depend on this value, it is best to specify one.
The following example is an ordered list with a nested ordered list in the second item. We are going to change the numbering as well as the alignment of the labels.
<ol> <li>Item 1</li> <li>Item 2 <ol> <li>Subitem 1</li> <li>Subitem 2</li> <li>Subitem 3</li> </ol> </li> <li>Item 3</li> </ol>
In the style sheet we say that the :before
pseudo element
of any li
under a ol
, no matter the level, is a
marker. In there, we increment the counter that is reset for each level of
ol
. We also display it with the lower-roman
counter
style instead of the default style (decimal
). This style will show
the effect of the right alignment of the text inside the label. The
marker-offset
property provides for a bit of space between the
label and the list item body.
The width
property deserves special attention. First of all
it defines the width of the labels. Since markers shouldn't influence the
positioning of the element they are attached to, the labels would stick out to
the left by the amount of the value of the width
property. In
order to compensate this, we have to add a margin-left
with the
same value to the list item itself.
ol { counter-reset: list-counter; } ol li { margin-left: 2em; } ol li:before { content: counter(list-counter, lower-roman) "."; counter-increment: list-counter; display: marker; marker-offset: 0.5em; text-align: right; width: 2em; }
The rendered result would like this:
- Item 1
- Item 2
- Subitem 1
- Subitem 2
- Subitem 3
- Item 3
Making Section Numbers Stick Out
Sometimes the text of the section titles must be aligned with the rest of
the material, at the left side for example. As consequence, if the titles also
have section numbers, those will stick out at the left side of the title, into
the margin, just like the title of the current section. This can be obtained by
specifying a :before
pseudo element for the section titles with
the display type marker
. Because markers shouldn't influence the
positioning of their associated element, the marker content is prepended. This
is the piece of style sheet you would need:
h2:before { display: marker; marker-offset: 0.5em; padding-right: 0pt; text-align: right; width: 3em; }
This Guide's Page Set-up
The page set-up of this guide is rather advanced and is therefore an interesting practical case. The difficulty lies in specifying the static regions if there are many kinds of pages and if for each of those the static regions are different. i.e. very specific.
In order to avoid an explosion of CSS property specifications for all
those regions, we can work in a sort of multidimensional way. This is possible
through the combination of two things. First, we have the CSS cascading
mechanism, which allows us to centralise common property specifications.
Second, the can make use of the fact that the class
attribute is a
space-separated list of names. Because of this, an element can belong to
several classes. These are the static regions of this guide:
<div class="first top"/> <div class="title first bottom"/> <div class="title first top"/> <div class="copy-right first bottom"/> <div class="copy-right first top"/> <div class="left bottom"><span/></div> <div class="right bottom"><span/></div> <div class="left top"><span/></div> <div class="right top"><span/></div> <div class="front left bottom"><span/></div> <div class="front right bottom"><span/></div> <div class="blank bottom"/> <div class="blank top"/>
Neither of them has a lot of content. It is all generated using the
span
element as a hook. For the empty div
elements no
content will be generated. You can see that all regions belong to more than one
class. The more classes they belong to, the more specific is the set of pages
they apply to. This is one dimension. The other is whether the static region is
a top or bottom region.
The first region, for example, is a bottom region that applies only to the
first page of the named page sequence called title
. This is expressed in
the style sheet as follows:
div.title.first { page: first-title; }
The rule applies if class
is title
and
first
. This is more specific then the following page assignment which
also occurs in the style sheet:
div.first { page: first; }
Another example is the pair of bottom regions for left and right pages.
They apply for left and right pages, no matter the page sequence. For the
front
page sequence, however, there is a more specific version. Making
it more specific is done by the two page assignments in the following style
sheet part. The style of the bottom region of the front part is a bit
different. It display the page numbers in lower Roman. The complete style is
obtained by cascading all the rules for the class bottom
. The first two
rules define the style for all bottom regions and the last one overrides the
counter style.
div.bottom { height: 3em; padding-top: 2em; region: bottom; } div.bottom > span:before { content: counter(page); } div.front.left { page: left-front; } div.front.right { page: right-front; } div.front.bottom > span:before { content: counter(page, lower-roman); }
For blank pages we want no static regions at all, at least not visually.
The presence of the top and bottom regions is defined generally through the
div.top
and div.bottom
rules. As a consequence, no
matter the page sequence, those static regions are always generated. All we
have to do now is making sure they don't contain anything. This is done by the
two empty regions with the class
attribute set to blank top
and blank bottom
respectively. Those regions are assigned to blank pages
with the following style sheet part:
div.blank { page: blank; }
There is one more special construct left to discuss: the absence of static
top regions on the first page of a chapter. As with blank pages they are not
really absent. They are merely made empty. It is in fact the first region with
the classes first
and top
. This region is assigned to the
first
pseudo page. All chapters are however in the named page
sequence main
. If we do nothing only the first page of the first chapter
will have an empty top region. We therefore should toggle the page
property without adding extra pages. This can be achieved by inserting an empty
div
element between the chapters with the class separator
.
The page assignment for that class is separator
. This named page is not
used for anything else. Since the element is empty no page sequence is
generated. The next main
element, however, will start a new page
sequence.
After the front matter not only the page number style changes to decimal,
but the page numbering is also reset. We can't just reset the page
counter in the main
page context, because then the numbering would be
reset for each chapter. Instead, the style sheet defines a
main-first
@page rule, which contains the same definitions as
main
and a page
counter reset on top of it. This page
is assigned to the first chapter only, using the first-child
pseudo-class on the h1
element.
A Two-column Article
Many articles and papers are formatted in two column mode. The title,
abstract, authors, etc. are usually displayed across the two columns. With two
extension properties it is possible to do this. The column-count
should be set to 2
in the page context. The title material can be
wrapped in a block element for which the column-span
property is
set to all
.
Initial Capitals
A typographical effect that is often used are
initial capitals. It consists of making the first letter of an article or
chapter stand out by rendering it bigger and perhaps in another font and/or
colour. In CSS this is supported through the :first-letter
pseudo element, which is described in section 5.12.2 of
[CSS2]. In CSSToXSLFO it is implemented with the
restriction that letter combinations, which are considered as one letter, are
not examined. In case you need that, you can always use the Unicode ligature
characters instead.
The technique was applied to the previous paragraph using the piece of
style sheet below. Note the second deviation from the specification being the
usage of the property vertical-align
while the float
property has the value none
. It is allowed in CSSToXSLFO because
otherwise we have no control over the alignment of the first letter with the
lines next to it. This depends on the font and will always require some trial
and error in order to get it right. The values for the other properties are
obtained in the same way. In fact, for this special case, we work around the
normal way a glyph is layed out in a line.
p:first-letter { font-family: serif-swash; font-size: 46pt; font-style: italic; float: left; line-height: 46pt; padding-right: 6pt; margin-bottom: -12pt; vertical-align: 9pt; }