Copyright © 2007 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
This module describes features often used in printed publications. In particular, this specification describes how CSS style sheets can express named strings, leaders, cross-references, footnotes, endnotes, running headers and footers, named flows, new counter styles, page and column floats, hyphenation, bookmarks, change bars, continuation markers, named page lists, and generated lists. Along with two other CSS3 modules – multicolumn layout and paged media – this module offers advanced functionality for presenting structured documents on paged media.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
The (archived) public mailing list www-style@w3.org (see instructions) is preferred for discussion of this specification. When sending e-mail, please put the text “css3-gcpm” in the subject, preferably like this: “[css3-gcpm] …summary of comment…”
This document was produced by the CSS Working Group (part of the Style Activity).
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This WD describes functionality at various levels of maturity. Some features have been part of other WDs in the past and have already been implemented. Other features are merely at the brainstorming stage. In general, features presented earlier in this draft are more mature that those presented later in the draft.
This CSS3 module has normative references to the following other CSS3 modules:
This CSS3 module has non-normative (informative) references to the following other CSS3 modules:
(This section is not normative.)
This specification describes various functionality which is commonly used in paper-based publishing. Some of the proposed functionality (e.g., hyphenation and the new list style types) may also used with other media types. However, this specification is only concerned with the 'print' media type.
This is an early and preliminary proposal that still needs a lot of work and we would especially welcome feedback from the community that works on document specifications.
To aid navigation in printed material, headers and footers are often printed in the page margins. [CSS3PAGE] describes how to place headers and footers on a page, but not how to fetch headers and footers from elements in the document. This specification offers two ways to achieve this. The first mechanism is named strings which copies the text (and not style, structure, or replaced content) from one element for later reuse. Named strings are described in this section. Later, a mechanism for moving elements (including its style and structure) into a running headers/footer is described.
Named strings can be thought of as variables that can hold one string of text. Named strings are created with the 'string-set' property which copies a string of text into the named string. Only text is copied; not style, structure, or replaced content. The only reason for creating a named string is to display the string later by using the 'content' property.
Discuss the name space of counters vs named strings
The scope of a named string is the page of the element to which the 'string-set' property is attached and subsequent pages. Is this correct?
There should be a more specific description of how to get to the text. For example, should all white space be preserved?
The 'string-set' property is defined as follows:
Name: | string-set |
Value: | [[ <identifier> <content-list>] [, <identifier> <content-list>]* ] | none |
Initial: | none |
Applies to: | all elements |
Inherited: | no |
Percentages: | N/A |
Media: | all |
Computed value: | as specified value |
The 'string-set' property
accepts a comma-separated list of named strings. Each named string is
followed by a content list that specifies which text to copy into the
named string. Whenever an element with value of 'string-set' different from 'none'
is encountered, the named strings are assigned
their respective value.
For the 'string-set' property, <content-list> expands to one or more of these, in any order:
dt { string-set: index first-letter, entry content } h1 { string-set: header "Chapter " counter(chapter) content }
The two tables below show how the above style sheet can set values on named strings. First, for the 'dt' element, the content is (say) "Amphibious":
element type | content | value of 'index' string | value of 'entry' string |
dt | "Amphibious" | "A" | "Amphibious" |
Second, for the 'h1'
element, the content is
(say) "Introduction" and the value of the 'chapter' counter is 1:
element type | content | value of 'chapter' counter | value of 'header' string |
h1 | "Introduction" | 1 | "Chapter 1 Introduction" |
The content of named strings can be recalled by using the 'string()'
value on the 'content' property. The 'string()'
value has one required argument, namely the
name of the string.
@page { @top-center { content: string(header) }} @page { @right-middle { content: string(index) }} @page { @top-left { content: string(entry) }} h1 { string-set: header "Chapter " counter(chapter) content } dt { string-set: index first-letter, entry content }
If the value of the named string is changed by an element on a certain
page, the named string may have several values. In order to specify which
of these values should be used, an optional argument is accepted on the
'string()'
value. This argument can have one of
four keywords:
'start'
: the named string's entry value for
that page is used.
'first'
: the value of the first assignment is
used. If there is no assignment on the page, the start value is used.
'first'
is the default value.
'last'
: the named string's exit value for that
page is used
'last-except'
: the named string's exit value
for that page is used, except on the page where the value was assigned.
On that page, the empty string is used.
In this example, the first term on the page will be shown in the top left corner and the last term on the page will be shown in the top right corner. In top center of the page, the first letter of first term will be shown.
@page { @top-left { content: string(entry, first) }} @page { @top-right { content: string(entry, last) }} @page { @top-center { content: string(index, first) }} dt { string-set: index first-letter, entry content }
'h1'
elements appear. On other
pages, the string of the previous 'h1'
element will
be shown.
@page { @top-center { content: string(chapter, last-except) }} h1 { string-set: chapter content }
A leader is a visual pattern that guides the eye. Typically, leaders are used to visually connect an entry in a list with a corresponding code. For example, there are often leaders between titles and page numbers in a table of contents (toc). Another example is the phone book where there are leaders between a name and a telephone number.
In CSS3, a leader is composed of series of glyph through the 'leader()'
value on the 'content' property. The functional notation accepts
one value which describe the glyph pattern that make up the leaders. These
values are allowed:
Using the keyword values is similar to setting a string value. The table below shows the equivalents:
Keyword | String | Comment |
---|---|---|
leader(dotted) | leader('. ')
| Note the space character inside the string |
leader(solid) | leader('_') | |
leader(space) | leader(' ')
| The string consists of one space character |
Some fonts may not have suitable glyphs for all patterns. For example, in some Eastern languages, the alignment of the shape within the glyph may not be optimal for creating leaders.
The string inside the parenthesis is called the leader string.
In its simplest form, the 'content' property
only takes one 'leader()'
value:
heading::after { content: leader(dotted) }
The leader string must be shown in full at least once and this
establishes the minimum length of the leader. To fill the available space,
the leader string is repeated as many times as possible in the writing
direction. At the end of the leader, a partial string pattern may be
shown. Or, partial strings be avoided? White
space in leaders is collapsed according to the value of 'white-space'
.
These properties influence the appearance of leaders: all font properties, text properties, 'letter-spacing', 'white-space', 'background', and 'color'.
Should other properties influence the appearance of leaders?
UAs should attempt to align leader patterns on a page. Is there a better way to say this
In a more complex example, the 'leader' value is combined with other values on the 'content' property:
ul.toc a::after {
content: leader('. . . ') target-counter(attr(href, url), page);
}
If the content connected by a leader end up on different lines, the leader will be present on all lines. Each leader fragment honors the minimum length of the leader.
Consider this code:
<style> .name::after { content: leader(dotted) } </style> <div class="entry"> <span class="name">John Doe</span> <span class="number">123456789</span> </div>
If the name and number end up on different lines (e.g., in a narrow column), it may be formatted like this:
John Doe.... ...123456789
To determine the length of the leaders, user agents must do the following for each line:
Consider this code:
<style>
cite::before { content: leader(' ') }
</style>
<blockquote>
Bla great bla bla world bla bla
empire bla bla color bla bla
history bla bla forever.
<cite>John Johnson</cite>
</blockquote>
Depending on the width of the containing block, this may be rendered as:
Bla great bla bla world bla bla empire bla bla color bla bla history bla bla forever. John Johnson
However, this rendering is preferable:
Bla great bla bla world bla bla empire bla bla color bla bla history bla bla forever. John Johnson
To indicate that John Johnson
should be kept on one line, this
rule can be added to the style sheet:
cite { text-wrap: suppress }
Until 'text-wrap' is widely supported, this rule can also be used:
cite { white-space: nowrap }
Here is another pleasant rendering of this example:
Bla great bla bla world bla bla empire bla bla color bla bla history bla bla forever. John Johnson
It is common to refer to other parts of a document by way of a section number (e.g,, "See section 3.4.1"), a page number (e.g,, "See discussion on page 72"), or a string (e.g., "See the chapter on Europe"). Being able to resolve these cross-references automatically saves time and errors.
Cross-reference are generated by styling the source anchor of a link in a special way. Instead of styling the source anchor by (say) showing it underlined in blue, the style sheet can (say) specify that the source anchor should be presented with a page number. For example, the string " (see page 72)" could be added to the link.
Here is the CSS code to achieve this on common HTML markup:
a::after { content: "(see page " target-counter(attr(href, url), page, decimal) ")" }
'target-counter'
and 'target-counters'
valuesNumerical cross-references are generated by 'target-counter'
and 'target-counters'
that fetch the value of a counter at
the target end of the link. These functions are similar to the 'counter()'
and 'counters()'
functions, except that they fetch counter values from remote elements.
'target-counter'
has two required arguments: the
url of the link, and the name of a counter. 'target-counters'
has three required arguments: the url
of the link, the name of a counter, and a separator string. An optional
argument at the end indicates which list style type to use when presenting
the resulting number; 'decimal'
being the default.
'target-text'
valueTextual cross-references are generated by 'target-text'
which fetches the textual content from the
target end of the link. Only text is copied; not style, structure, or
replaced content. 'target-text'
has one required
argument: the url of the link. An optional second argument specifies
exactly which content is generated. There are four possible values:
'content'
refers to the textual content of the
element, not including the content of its ::before and ::after
pseudo-element. The content of the element's descendants, including their
respective ::before and ::after pseudo-elements, are included in the
returned content.
'before'
refers to the content of the element's
::before pseudo-element
'after'
refers to the content of the element's
::after pseudo-element
'first-letter'
refers to the first letter of
the textual content of the element, not including the content of its
::before and ::after pseudo-element.
The default value is 'content'
.
To generate this text
from this markup:See Chapter 3 ("A better way") on page 31 for an in-depth evaluation.
<p>See <a href="#chx">this chapter</a> for an in-depth evaluation. ... <h2 id="chx">A better way</h2>this CSS code can be used:
h2 { counter-increment: chapter } a { content: "Chapter " target-counter(attr(href, url), chapter)' ("'
target-text(attr(href), content)'") on page '
target-counter(attr(href, url), page);
Footnotes is another device used in traditional printing. A footnote is a note placed at the bottom of a page that comments on or cites a reference for a designated part of the text. References to footnotes are marked with a note-call in the main text.
In its simplest form, a making a footnote is very simple.
<style> .footnote { float: note } </style> <p>A sentence consists of words. <span class="footnote">Most often.</span>.
In this example, the text Most often.
will be placed in a
footnote. A note-call will be left behind in the main text and a
corresponding marker will be shown next to the footnote. Here is one
possible rendering:
A sentence consists of words. ¹ ¹ Most often.
To support legacy browsers, it is often better to make a link to the note rather than including the text inline. This example shows how to fetch the content of a note and place it in a footnote.
<style> @media print { .footnote { float: footnote; content: target-move(attr(href, url)) } .marker { display: none } } </style> ... <p>A sentence consists of words<a class="footnote" href="#words"> [3]</a>. ... <p id=words><span class="marker">[3]</span> Most often.
When shown in (say) screen mode or a legacy browser, the note-call will be shown as a clickable link to an end note. When printed according to this specification, there will be a footnote:
A sentence consists of words¹. ¹ Most often.
In order to support footnotes in CSS, the following functionality is added:
'footnote'
'@footnote'
'::footnote-call'
and
'::footnote-marker'
'footnote'
'super-decimal'
, and symbol(...)
'target-move()'
These items are described below.
An element with 'float: footnote'
(called the
footnote element) is moved to the footnote area and a
note-call pseudo-element is put in its original place.
span.footnote { float: footnote; }
For each new footnote element, the predefined 'footnote'
counter is incremented due to a setting in the
default style sheet.
Footnote elements are presented inside the footnote area, but they inherit through their normal place in structure of the document.
There has been a number of proposals on how to achieve this,
including 'position: footnote'
, 'flow: footnote'
, and 'display:
footnote'
. The current thinking is that 'float' is suitable as the content still takes up
space.
All elements with 'float: footnote'
are moved to
boxes with 'content: pending(footnote)'. As specified in the default style
sheet, this is the case for the @footnote area.
This code is part of the suggested default style sheet:
@footnote { content: pending(footnote) }
The footnote area is found at the bottom of the page area. Page-based
floats with the 'bottom'
value will be placed above
the footnote area. Potentially, every page has a footnote area. If there
are no footnotes on the page, the footnote area will not take up any
space. If there are footnotes on a page, the layout of the footnote area
will be determined by the properties/values set on it, and by the footnote
elements elements inside it.
These properties apply to the footnote area: 'content', 'border', 'padding', 'margin', 'background', 'column-span' and 'border-length'.
This example uses many of the applicable properties on @footnote:
@footnote { margin-top: 0.5em; border-top: thin solid black; border-length: 4em; padding-top: 0.5em; column-span: all; }
The result of this code is that a footnote area will appear on every page with footnote elements on it. The footnote area will have some margin above the border. Unlike normal borders, only part of the border is visible due to the 'border-length' property. Underneath the border, there will be padding. Finally, 'column-span' declares that the footnote area will span all columns, not just one (which is the initial value).
Name: | border-width |
Value: | <length> | auto |
Initial: | auto |
Applies to: | @footnote areas |
Inherited: | no |
Percentages: | refer to normal length of horizontal border of footnote area |
Media: | visual |
Computed value: | the absolute length |
The purpose of the 'border-width' property is to describe one common way of separating footnotes from other content: where a short horizontal bar is used as a separator.
A sentence consists of words¹. ______ ¹ Most often.
The 'border-width' property affects the rendering of horizontal borders of the footnote area. Vertical borders are not affected. If the length of horizontal borders are longer than the value of this property, part of the border will be invisible and the background of the footnote area will be shown instead. Which part of the border is made invisible depends on the inline direction of the text; if the direction is left-to-right, the left pat of the border will be visible, and vice versa. If the inline direction is not horizontal, this property has no effect.
Should it be called 'max-border-length', 'border-width', or 'max-border-width'?
In published books, it is customary for the footnote area to be limited to less than half the height of the page area. Long footnotes may need more space, and the customary solution is for footnotes to span several pages. To achieve this, the 'max-height' property should be used. However, footnotes spanning several pages is an advanced feature which is not a conformance requirement for this specification.
Footnotes in tables and floats may be problematic. In some cases, the author may want the footnote to go at the end of the table or float instead of the bottom of the page.
When an element is moved to the footnote area, a note call is
left behind. The content and style of the footnote-call is set on the
'footnote-call'
pseudo-element.
span.footnote::footnote-call { content: counter(footnote, super-decimal) }In this example, the resulting note call is a super-scripted decimal number.
Should any white space characters between the note-call and and the preceding content be removed?
A ::note-marker pseudo-element is added to each footnote element. It typically contains the same numbers/symbols as the note-call pseudo-element to link the two together.
.footnote::footnote-marker { content: counter(footnote, super-decimal); list-style-position: outside; }
Marker elements are discussed in more detail in the CSS Lists module [CSS3LIST]. One suggested change to that module is to honor the value of 'list-style-position' on the ::footnote-marker pseudo-element itself rather than the corresponding list-item element.
Footnotes are counted with a predefined 'footnote'
counter. When an element with 'position: footnote'
is encountered, the 'footnote'
counter is automatically incremented. An
element with 'float: footnote'
inherits from its
parent, not from @footnote.
The reason for having a predefined "footnote" counter is to avoid having to set "counter-increment: footnote" every time one sets "float: footnote". However, is this a good enough reason?
The footnote counter can be reset on a page basis.
@page { reset-counter: footnote }
Suggested constraints for the placement of footnotes:
'target-move'
valueIn order to fetch the content of another element (e.g., a linked note),
the 'target-move'
value is introduced. The value
uses a functional notation and expects a URI value as argument. In
combination with the 'content' property,
target elements can be moved to the anchor element.
<style> @media print { .footnote { float: footnote; content: target-move(attr(href, url)) } .marker { display: none } } </style> ... <p>A sentence consists of words [3]</a>. ... <p id=words><span class="marker">[3]</span> Most often.
As a result of the 'target-move'
value, the last
p
element is moved from it normal place of presentation and
into the footnote.
Describe in more detail.
Endnotes are similar to footnotes, except that they are placed at the end of a section rather than at the bottom of a page. Some documents use both footnotes and endnotes.
Do we need endnotes, given that 'target-move' supports legacy endnote-like renderings?
To support endnotes, a new value on 'float' is proposed.
span.note { float: endnote; } body::after { content: pending(note) }
Elements with 'float: endnote'
are moved to where
'content: pending(endnote)'
is set. If 'content: pending(endnote)'
is not set, elements are
moved to the end of the document.
div.chapter::after { content: pending(endnote); display: block; }
Like for footnotes, a ::endnote-call pseudo element is left at the place of origin.
Like for footnotes, a predefined 'endnote'
counter is incremented for every endnote element due to a setting in the
default style sheet.
Like for footnotes, a ::endnote-marker pseudo-element is generated at the place of presentation.
Like for footnotes, the content of ::endnote-call and ::endnote-marker pseudo-elements can be set with the 'content' property.
Footnotes and endnotes are very similar and it may seem
excessive to define different call and marker types for them. The reason
for doing so is to create hooks to be used in the default style sheets. As
a result, changing 'float: footnote'
to 'float: endnote'
will just work.
Headers and footers can be achieved through named strings, as described above. However, named strings only hold textual content; any style, structure or replaced content associated with the element is ignored. To overcome this limitation, a way of producing running headers and footers by way of moving elements is introduced.
Unlike footnotes and endnotes, elements that are moved into headers and
footers are repeated on several pages; they are said to be running
elements. To support running elements, a new value – running()
– is introduced on the 'position'
property. It has one required argument: the name of the running element
which it creates. Running elements are not real elements and their
creation does not alter the document structure. A running element has a
name. Like counters and named strings, the name of a running element is
chosen by the style sheet author. A running element can hold one element
and its descendants. Whenever a new element is assigned to a running
element, the old value is lost. The content of the running element can be
referred to by way of the 'element(<element>)'
value.
title { position: running(header) } @page { @top-center { content: element(header) } }
Like the 'string()'
value, the 'element()'
value accepts an optional second argument
which is one of: 'start'
, 'first'
, 'last'
, 'last-except'
. The keywords have the same meaning as for
the 'string()'
value.
One notable difference between named strings and running elements is
that 'string()'
copies the textual content
of an element while 'running()'
moves the
presentation of the element.
In this example, the header is hidden from view in all media types except print. On printed pages, the header is displayed top center on all pages, except where h1 elements appear.
<style> div.header { display: none } @media print { div.header { display: block; position: running(header); } @page { @top-center { content: element(header, last-except) }} </style> ... <div class="header">Introduction</div> <h1 class="chapter">An introduction</div>
This code illustrates how to change the running header on one page only.
... <style> @page { @top-center { content: element(header, first) }} .header { position: running(header) } .once { font-weight: bold } </style> ... <div class="header">Not now</div> <p>Da di ha di da di ... <span class="header once">NOW!</span> <span class="header">Not now</span> ... da di ha di hum.</p> ...The header is "Not now" from the outset, due to the "div" element. The first "span" element changes it to "NOW!" on the page where the "span" element would have appeared. The second "span" element, which would have appeared on the same page as the first is not used as the
'first'
keyword has been specified. However, the second
"span" element still sets the exit value for "header" and this value is
then used on the next page.It is sometimes useful to move elements out of their normal flow and into other containers. CSS is not a transformation language, so the motivation for supporting flows is presentational rather than structural. Mechanisms to support footnotes, endnotes and running headers and footers – which are conventional ways of moving content – have been described above. In this section, a more generic mechanism called named flows is described.
Not quite described yet, but at least an example is provided
P.side { position: flow(side) } DIV.side { content: pending(side); }
Elements that are moved into a new flow are removed from their current
position to where 'pending(<flow>)'
has been
set. Like for footnotes and endnotes, elements that are moved into a named
flow are only displayed once.
If 'pending(<flow>)'
isn't set
anywhere, the content should be place at the end?
Should a ::note-call be left in the original location?
Should it be possible to add footnotes/endnotes by way of named flows?
'super-decimal'
list-style-typeA new list-style-type, 'super-decimal'
, is
introduced to better support footnotes. Small, super-scripted footnote
calls are common; the first three numbers have code points in Latin-1 and
some font families have even more super-scripted glyphs. The 'super-decimal'
keyword allow these font resources to be
used and replaces the used of 'font-size' and
'vertical-align' (which prohibit the use of
special-purpose glyphs).
CSS defines a number of predefined list style types for the 'list-style-type' property and other places where a
list-style-type value is accepted. Some styles repeat the same glyph
(e.g., 'disc'
and 'circle'
)
while others have lists of glyphs (e.g., 'decimal'
,
and 'lower-roman'
). To increase the range of lists
that can be achieved through CSS without adding lots of new keywords,
@counter-style rules are introduced. By using @counter-style, a style
sheet can name new counter styles.
An @counter-style rule consists of the keyword '@counter-style'
, followed by the name of the symbol
counter style, followed by a space-separated list of strings.
@counter-style daggers "*" "\2020" "\2021" "\A7" "#"; ol { list-style-type: daggers } @counter-style ordinal "1st" "2nd" "3rd" "4th"; h1:before { content: counter(chapter, ordinal) " chapter" }
The first string in the list represents number one, the second string
represents number two, etc. If a counter has a value less than one, or
greater than the number of strings in the list, the rendering will be as
if the 'decimal'
list style type had been
specified.
Consider this example:
@counter-style ordinal "1st" "2nd" "3rd" "4th"; ordered-list { counter-reset: items -1 } list-item { counter-increment: items 2 }
For a series of list-item elements inside an ordered-list element, the value of the items counter will be -1, 1, 3, 5, 7 etc. Given that the ordinal counter style only defines a counter style for 1, 2, 3, and 4, the list will be numbered "-1", "1st", "3rd", "5", "7" etc.
@counter-style graphic url("1.gif") url("2.gif") url("3.gif")
'symbol(...)'
list-style-typeA new list-style-type with a functional notation is introduced to avoid the indirection of having to name counter styles. The ''symbol(...)'' value takes a comma-separated list of strings, just like named counter styles described above.
ol { list-style: "*" "\2020" "\2021" "\A7" "#" }
::footnote-call { content: counter(footnote, symbols('*','+'
,'!'
)) }
Should there be a way to indicate the behavior if there are more items than strings? Proposals include: "alphabetic", "enumerate", "numeric", "cycle", "ideographic".
In CSS2, the 'float' property is used to shift content to the left or right on the current line. This specification extends the property with several new values to allow content to be shifted to places commonly used in printed documents. Several of the new keywords can or must be combined with each other. The order of the keywords is insignificant.
This code serves as the base document for the examples of this section:
<html> <style> div { column-width: 15em; column-gap: 2em; /* shown in red below */ column-rule: thin solid black; /* shown in black below */ padding: 1em; /* shown in blue below */ } img { display: block; /* shown in dark gray below */ } </style> <body> <div> Lorem ipsum dolor sit amet. Nam at jus. <img src="foo"/> Sed imp er di et ris. Cur abi tur et sapen. ... </div> </body> </html>
This code can be rendered as:
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Vivamus a metus.
Aenean at risus
pharetra ante luctu
feugiat quis enim.
Cum sociis natoque
penatibus et magni.
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Vivamus a metus.
Aenean at risus
pharetra ante luctu
feugiat quis enim.
Cum sociis natoque
penatibus et magni.
If this code is added to the base document:
img { float: right }
it may be rendered as:
Lorem ipsum dolor
sit amet. Nam at jus.
Sed
imp
er di
et ris.
Cur
abi
tur et sapen. Fusce
sed ligula a turpis.
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Vivamus a metus.
Aenean at risus
pharetra ante luctu
feugiat quis enim.
Cum sociis natoque
penatibus et magni.
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Vivamus a metus.
Aenean at risus
pharetra ante luctu
feugiat quis enim.
Cum sociis natoque
penatibus et magni.
These examples float the image to the bottom of the page.
img { float: page bottom }
img { float: top right column }
img { float: column gap; width: 120%; }
Lorem ipsum dolor
sit amet. Nam at jus.
Sed
imp
er di
et ris.
Cur
abi
tur et sapen. Fusce
sed ligula a turpis.
Lorem ipsum dolor
sit amet. Nam at jus.
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Vivamus a metus.
Aenean at risus
pharetra ante luctu
feugiat quis enim.
Cum sociis natoque
penatibus et magni.
This example floats the image to the top right of the column generator
img { float: top right column; column-span: 2; width: 100%; }
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Vivamus a metus.
Aenean at risus
pharetra ante luctu
feugiat quis enim.
Cum sociis natoque
penatibus et magni.
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
If combined with 'left', 'right', 'inside' or 'outside', the element will float to the respective side, while allowing other content around it. In other cases, the element will be cover the width of the page or column.
img { float: bottom; width: 100%; }
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Vivamus a metus.
Aenean at risus
pharetra ante luctu
feugiat quis enim.
Cum sociis natoque
penatibus et magni.
Lorem ipsum dolor
sit amet. Nam at jus.
Sed imp er di et ris.
Cur abi tur et sapen.
Vivamus a metus.
Aenean at risus
pharetra ante luctu
feugiat quis enim.
Cum sociis natoque
penatibus et magni.
If combined with 'left', 'right', 'inside' or 'outside', the element will float to the respective side, possibly with other content on its side. In other cases, the element will be cover the width of the page or column.
These two declarations result in identical presentations:
img { float: next page } img { float: top next page }
img { float: next page unless-room }
The image is only shown if there is room on the current page or column.
img { float: dev-null unless-room }
Some alternative names for this value are: 'six-foot-under', 'mariana-trench', 'great-beyond', 'valhalla'.
The 'marks' property from [CSS2] is part of this specification.
The CSS3 Text Module [CSS3TEXT] defines the 'hyphenate' property which adds support for hyphenation through style sheets. This specification defines more properties to further refine hyphenation. The description of the 'hyphenate' property is included for reference purposes.
Name: | hyphenate |
Value: | none | auto |
Initial: | none |
Applies to: | all elements |
Inherited: | yes |
Percentages: | N/A |
Media: | visual |
Computed value: | specified value |
Name: | hyphenate-dictionary |
Value: | auto | <uri> |
Initial: | auto |
Applies to: | all elements |
Inherited: | yes |
Percentages: | N/A |
Media: | visual |
Computed value: | specified value |
This property specifies which hyphenate-dictionary to use. The 'auto' value indicates that the built-in dictionaries, if any, should be used.
Name: | hyphenate-before |
Value: | <integer> |
Initial: | 2 |
Applies to: | all elements |
Inherited: | yes |
Percentages: | N/A |
Media: | visual |
Computed value: | specified value |
This property specifies the minimum number of characters in a hyphenated word before the hyphenation character.
Name: | hyphenate-after |
Value: | <integer> |
Initial: | 2 |
Applies to: | all elements |
Inherited: | yes |
Percentages: | N/A |
Media: | visual |
Computed value: | specified value |
This property specifies the minimum number of characters in a hyphenated word after the hyphenation character.
Name: | hyphenate-lines |
Value: | none | <integer> |
Initial: | none |
Applies to: | all elements |
Inherited: | yes |
Percentages: | N/A |
Media: | visual |
Computed value: | specified value |
This property specifies the maximum number of successive hyphenated lines in an element. The 'none' value means that there is no limit.
Name: | hyphenate-character |
Value: | <string> |
Initial: | A string consisting of the Unicode hyphen character U+2010 |
Applies to: | all elements |
Inherited: | yes |
Percentages: | N/A |
Media: | visual |
Computed value: | specified value |
This property specifies a string that is shown when a hyphenate-break occurs. Typically, the string consists of only one character.
Some document formats have the capability of holding bookmarks. To generate these bookmarks, three properties are defined.
Name: | bookmark-level |
Value: | none | <integer> |
Initial: | none |
Applies to: | all elements |
Inherited: | no |
Percentages: | N/A |
Media: | all |
Computed value: | specified value |
h1 { bookmark-level: 1 } h2 { bookmark-level: 2 } h3 { bookmark-level: 3 }
Name: | bookmark-label |
Value: | content | <attr> | <string> |
Initial: | content |
Applies to: | all elements |
Inherited: | no |
Percentages: | N/A |
Media: | all |
Computed value: | specified value |
This property specifies the label of the bookmark.
a { bookmark-label: attr(title, string) } h1 { bookmark-label: self } #frog { bookmark-label: "The green frog";
Name: | bookmark-target |
Value: | self | <uri> | <attr> |
Initial: | self |
Applies to: | all elements |
Inherited: | no |
Percentages: | N/A |
Media: | all |
Computed value: | For URI values, the absolute URI; for attr() values, the resulting URI or string; for other keywords, as specified. |
This property specifies the target of the bookmark link.
.bookmark { bookmark-label: attr(title, string); bookmark-target: attr(href, url); } ... <a class="bookmark" title="The green pear" href="#pears"/>
XSL uses a different list of properties. Reuse of these properties has been considered.
Change bars are used to indicate that a change has occurred in a section of a document. The changed section does not necessarily correspond to an element and (given the tree structure of common markup languages) it is not always possible to create any such element.
To avoid these limitations, the beginning of a change mark is associated with one document and the end of a change mark is associated with another document.
p.change-start { change-bar: thin solid red; change-bar-class: change1; change-bar-offset: 0.3em; change-bar-side: left; /* or right, inside, outside */ } p.change-end { change-bar-class: change1; }
This model is borrowed from XSL.
Continuation markers are used to indicate that an element continues from one page to the next. The ::before-break pseudo-element is shown after the last line before the page break. The ::after-break pseudo-element is shown before the first line after the page break. Continuation markers otherwise act as ::marker pseudo-elements.
::before-break { content: image(to-arrow.png); } ::after-break { content: image(from-arrow.png); }
In CSS 2.0, the 'page' property takes one value. The value can be 'auto' or a named page. In the case where a named page is specified, a page break is inserted and the element is put on the named page.
In this specification, a list of values is allowed in the 'page' property. As content is laid out and new pages are generated, the list is traversed linearly starting at the first list item. One page is created per item in the list. If more pages are required than there are items in the list, the last item is repeated as many times as necessary.
h2 { page: no-header auto }
This means: the content of an h2 element should be laid out on a 'no-header' page, thereafter the auto page (which is the initial value). The last value (auto) is repeated if there is need for more pages.
The last value in the list becomes the leaving value which is compared with the first item the 'page' property of the next element. If those two values are different, a page break is generated.
Consider this example:
h2 { page: no-header auto } p { page: auto } <h2>foo</h2> <p>bar</p>
There would be no page break between H2 and P elements as the last named page on H2 is the same as the first (and only) named page on the P element.
Books typically have sections that are extracted from the main content, for example, a the table of contents (toc) in the front and an index at the back. Also, there are glossaries and lists of figures (lof) and lists of tables (lot). These sections can all be referred to as generated lists; they are generated from the main content, and have the nature of lists. Some lists are sorted alphabetically (e.g., an index and a glossary), and others reflect the order of the content (toc, lof, lot).
To generate lists in CSS, a prototype container must be
established. Other elements will be flowed into the prototype container,
but it can also contain content of its own. Elements with a 'make-element'
value other than 'none'
will generate an element
inside a prototype container. The value of 'make-element' is the ID of a prototype entry
element which is replicated inside the prototype container, and a
specification of the content which is to be inserted into the generated
list.
Here is an example of how to generate a toc with leaders and page numbers.
...
<style>
#toc { prototype: container }
#toc-entry {
prototype-insert-position: current;
font-size: 14pt }
#toc-entry::after { content: leader('. ') source-counter(page) }
h1.chapter { make-element: toc-entry content }
</style>
...
<div id="toc">
<h1>Table of contents</h1>
<div id="toc-entry"></div>
</div>
...
<h1 class="chapter">Introduction</h1>
...
There are three new properties and one new value on the 'content' property in the above example. This rule:
#toc { prototype: container }
declares that the #toc element is a prototype container that accepts generated lists. Prototype containers cannot be nested. Each container keeps a position of where the last generated list item was added. This rule:
prototype-insert-position: current;
specifies that entities in the #toc are to be added at the current position, i.e., after the previous generated list item. This code:
#toc-entry::after { content: leader('. ') source-counter(page) }
has one new value (''source-counter(page)'') which fetches the value of
the 'page'
counter from the source element, i.e.,
the element which has a 'make-element'
declaration:
h1.chapter { make-element: toc-entry content }
The above rule creates one new element. The new element is isomorphic to the #toc-entry element and is inserted according to the 'prototype-insert-position' of #toc-entry.
Glossaries provide a new kind of challenge: entries are sorted alphabetically.
Here is an example of how to generate a glossary:
... <style> #glossary { prototype: container } #glossary-term { insert-position: sorted } #glossary-definition { insert-position: current } </style> ... <div id="glossary"> <h2>Glossary of terms</h2> <dl> <dt id="glossary-term">...</dt> <dd id="glossary-definition">...</dd> </dl> </div> ... <h1 class="chapter">Introduction</h1> ...
By inserting the term 'sorted'
and the
definition in the 'current'
position, terms will
be sorted alphabetically with their respective definition following.
An index is a generated list that is sorted alphabetically, just like glossaries. In addition, indexes often have single letters in large font sizes to help humans navigate. For example, all index entries starting with "s" is placed under a large capital "S". There should only be one large capital "S", and if there are no index entries starting with "s" the large "S" isn't shown.
To achieve this kind of presentation, the following strategy is suggested: for every index entry that is encountered, two elements are generated. One is the large capital letter, and the other is the index entry itself. To avoid having one large capital letter before each index entry, the 'insert-policy' property declares that identical generated list elements are to be deleted.
... <style> #index { prototype: container } #index-marker { insert-position: sorted insert-policy: unique; text-transform: uppercase } #index-entry { insert-position: sorted } #index-entry::after { content: leader(. . ) source-counter(page) } dfn.entry { make-element: index-marker first-letter, index-entry content } </style> ... <p>An <dfn>emphasized element</dfn> stands out.</p> ...
Here is a more complex example with several types of generated lists. Note how multilevel tocs require a prototype container without any additional content. Also, notice how the "acronym" element generates an entry both in the index and in the list of acronyms.
<style> #toc-container { prototype: container } #toc-entry-section { font-size: large; insert-position: current } #toc-entry-subsection { font-size: medium; insert-position: current } #toc-entry-section::after, #toc-entry-subsection::after { content: leader('. ') source-counter(page) } #acronym-list { prototype: container } #acronym-term { insert-position: sorted } #acronym-definition { insert-position: current } #index { prototype: container } #index-marker { insert-position: sorted insert-policy: unique; } #index-entry { insert-position: sorted } #index-entry::after { content: leader(. . ) source-counter(page) } h2 { make-element: toc-entry content } h3 { make-element: toc-entry content } acronym { make-element: index-marker first-letter, index-entry content, acronym content, acronym-definition attr(title); } dfn { make-element: index-marker first-letter(), index-entry content } </style> <div id="toc"> <h2>Table of contents</h2> <div id="toc-container"> <div id="toc-entry-section"></div> <div id="toc-entry-subsection"></div> </div> </div> <div id="acronym-list"> <h2>List of acronyms</h2> <dl> <dt id="acronym"></dt> <dd id="acronym-definition"></dd> </dl> </div> <div id="index"> <h2>Index</h2> <div id="index-marker"></div> <div id="index-entry"></div> </div> <body> <h2>Introduction</h2> <p>This part defines the a acronym: <acronym title="HyperText Markup Language">HTML</acronym>. <h3>More to learn</h3> <p>An <dfn>emphasized element</dfn> element stands out. </body>
::footnote-call { counter-increment: footnote; content: counter(footnote, super-decimal); } ::footnote-marker { content: counter(footnote, super-decimal); } @footnote { pending(footnote); counter-reset: footnote; } ::endnote-call { content: " [" counter(endnote, decimal) "]"; counter-increment: endnote; } ::endnote-marker { content: "[" counter(endnote, decimal) "]"; } h1 { bookmark-level: 1 } h2 { bookmark-level: 2 } h3 { bookmark-level: 3 } h4 { bookmark-level: 4 } h5 { bookmark-level: 5 } h6 { bookmark-level: 6 }
There is an issue wrt footnotes vs. endnotes. Currently,
::note-call and ::note-marker are used in both cases, but the default
style sheet favors footnotes (as the footnote counter is used). There are
two ways to resolve this: (a) only have one counter ("note") in the
default style sheet or (b) require changes to the default style sheet in
order to use end notes: .endnote ::note-marker { content:
counter(endnote) }
This document has been improved by Bert Bos, Michael Day, Melinda Grant, David Baron, Markus Mielke, Steve Zilles and Ian Hickson. [more to be added] Laurens Holst, Mike Bremford, Allan Sandfeld Jensen, Kelly Miller, Werner Donné, Tarquin (Mark) Wilton-Jones, Michel Fortin.
Property | Values | Initial | Applies to | Inh. | Percentages | Media |
---|---|---|---|---|---|---|
bookmark-label | content | <attr> | <string> | content | all elements | no | N/A | all |
bookmark-level | none | <integer> | none | all elements | no | N/A | all |
bookmark-target | self | <uri> | <attr> | self | all elements | no | N/A | all |
border-width | <length> | auto | auto | @footnote areas | no | refer to normal length of horizontal border of footnote area | visual |
hyphenate-after | <integer> | 2 | all elements | yes | N/A | visual |
hyphenate-before | <integer> | 2 | all elements | yes | N/A | visual |
hyphenate-character | <string> | A string consisting of the Unicode hyphen character U+2010 | all elements | yes | N/A | visual |
hyphenate-dictionary | auto | <uri> | auto | all elements | yes | N/A | visual |
hyphenate-lines | none | <integer> | none | all elements | yes | N/A | visual |
hyphenate | none | auto | none | all elements | yes | N/A | visual |
string-set | [[ <identifier> <content-list>] [, <identifier> <content-list>]* ] | none | none | all elements | no | N/A | all |