CSS Page Floats

Editor’s Draft,

This version:
http://dev.w3.org/csswg/css-page-floats/
Previous Versions:
https://hg.csswg.org/drafts/raw-file/108d7e3ff204/css-page-floats/Overview.html
Feedback:
www-style@w3.org with subject line “[css-page-floats] … message topic …” (archives)
Issue Tracking:
Inline In Spec
Editor:
(Vivliostyle)
Former Editor:
(Opera Software)

Abstract

This module describes features often used in printed publications. Figures and photos are often moved to the top or bottom of columns and pages, along with their captions. Some elements (e.g., call-outs) push aside other content in the flow of text, and sometimes one column is given a different styling than others. This draft describes how to achieve these effects, both on paper and screens.

CSS is a language for describing the rendering of structured documents (such as HTML and XML) on screen, on paper, in speech, etc.

Status of this document

This is a public copy of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as 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 “css-page-floats” in the subject, preferably like this: “[css-page-floats] …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 document is governed by the 1 August 2014 W3C Process Document.

Table of Contents

1. Introduction

This section is not normative.

This module describes features often used in printed publications. Figures and photos are often moved to the top or bottom of columns and pages, along with their captions. Some elements (e.g., call-outs) push aside other content in the flow of text, and sometimes one column is given a different styling than others. This draft describes how to achieve these effects, both on paper and screens.

2. Overview

In page-based layouts, images and figures are often displayed at the top or bottom of pages. This specificaton adds new keywords on the float property to create page floats. A page float can float inside its natural column/page, or its placement can be deferred to a following column/page with the float-defer properties. Page floats can be set to span several columns, thereby supporting commonly used newspaper layouts. New values on the clear property adds further ways of refining layouts with page floats.

Not all multicol elements are constrained by the page box. Therefore, a more accurate term for page floats may be column floats as all of them are constrained by the column box. However, in most cases, page floats seems like a better term.

3. Floating to the top/bottom: top, bottom, snap

These new keywords on float have been added:

top
The float is floated to the top of the column
bottom
The float is floated to the bottom of the column
snap(<length> <length>? [, top | bottom | near ]?)
Makes the element float to the top or bottom if it naturally appears within a certain distance from the top or bottom. The length value(s) specifies the maxium distance from the top/bottom that an element must be within in order to be floated; one length value specifies the distance from both the top and the bottom, two length values specify the distance from the top and bottom, respectively.

The optional keyword value specifies where the element is floated: top, bottom, or the nearest of the two. The initial value is near. If near is in effect and the element is within the specified distance both from the top and the bottom, bottom wins.

An element is considered to be a float if it has a snap() value, even if the element does not appear within the specified distance. This way, it can be determined whether an element is float or not without laying out the document.

snap
same as snap(2em, near)

These new keywords only apply in paged media; in continous media declarations with these keywords are ignored.

Elements with any of these new keywords are called 'page floats'. Each page float has a natural column, which is the column where the element would have started to appears it it was not a float.

Also, each page float has a natural page, which is the page where the element would have started if the was not a float. Unless other constrained by lack of space or other float-* properties, page floats should appear in their natural column on the natural page.

Float figure to top of natural column:
.figure { float: top }

sample rendering

.figure { float: top; width: 50% }

sample rendering

In this example, a figure naturally appears close to a column break. There is not enough space for the figure in the first column, and it is therefore placed in the second column, leaving white space at the bottom of the first column.

sample rendering

To avoid the white space, the image can be floated to the nearest edge (in the block direction):

.figure { float: snap }

In this example, the figure is already at the nearest edge, so it does not move. However, page floats allow subsequent content to be displayed before the page float and the white space can therefore be filled:

sample rendering

In this example, two figures naturally appear in the text flow:

sample rendering

A typographer would typically try to avoid single lines of text above/below figures, which can be achieved with:

div.figure { float: snap(1.5em) }

The length value specifies the reach of the snap function; in this example the second figure is affected, but not the first.

In this example, two figures naturally appear in the text flow:

sample rendering

To make the figures snap to the nearest edges, this code can be applied:

div.figure { float: snap(2.5em) }

The resultant rendering is:

sample rendering

Float figure to top of the natural column, spanning all columns:

.figure { float: top; column-span: all }

sample redering

In this example, tables will snap to the top/bottom if the top/bottom of the border box is closer than 3em from the top/bottom of the page/column.
table { float: snap }
table { float: snap(3em) }
table { float: snap(3em, bottom) }
table { float: snap(3em 2em, bottom) }

Do numeric values, to represent line numbers, make sense, like for orphans/widows?

4. Spanning columns

The column-span property is extended with integer values so that elements can span several columns. If the specified integer value is equal to, or larger than the number of columns in the multicol element, the number of columns spanned will be the same as if 'column-span: all' had been specified.

In this example, a commonly used newspaper layout is easily described:
body { columns: 3 }
img.A { column-span: 2; width: 100% }  /* image spans two columns */
.one { column-span: 2 }                /* lead paragraph spans two columns */

sample rendering

Further, the page value is added to column-span so that the page (and not the column or element) becomes the reference.

In this example, the footer is floated to the bottom of the last page (and not the bottom of the article element):
footer { float: bottom; column-span: page }

<article>
  ...
  <footer>...<.footer>
</article>

An alternative way to express this would be to add a separate propertye, e.g., float-reference: column | multicol | page

5. Deferring floats: float-defer-column, float-defer-page

A page float can be deferred to a following column/page with these new properties:

5.1. float-defer-column

Name: float-defer-column
Value: <integer> | last | none
Initial: none
Applies to: page floats
Inherited: no
Percentages: N/A
Media: visual
Computed value: specified value

5.2. float-defer-page

Name: float-defer-page
Value: <integer> | last | none
Initial: none
Applies to: page floats
Inherited: no
Percentages: N/A
Media: visual
Computed value: specified value

These properties specify whether page floats should appear in their natural column/page, or in a following column/page. Values are:

none
the page float appears in the natural column/page
<integer>
A positive integer value indicates that the page float should be displayed in a following column/page. A negative integer value indicates that the page float should be displayed in a following column/page, counted from the last column/page. When counting columns, the starting point is the last column of the multicol element on the natural page. When counting pages, the starting point is the last page of the multicol element.
Float figure to the top of the column that follows the natural column:
.figure { float: top }
.figure { float-defer-column: 1 }
Float figure to the top of the next-to-last column:
.figure { float: top; float-defer-column: -1 }

sample rendering

Float figure to top of the last column of the multicol element on the current page:
.figure { float: top; float-defer-column: last }

sample rendering

In combination with column-span, the figure is floated to the top corner of the multicol element on that page:
.figure { float: top; column-span: 2; float-defer-column: last; width: 100% }

sample rendering

Float figure to the top of the second column, spanning two columns:
.figure {
  float: top; column-span: 2;
  float-defer-column: 1;
}

sample rendering

Float figure to the top right, leaving one full column:
.figure {
  float: top; column-span: 2;
  float-defer-column: -1;
}

sample rendering

Given that there are four columnn, the same layout would be achived with this code:

.figure {
  float: top; column-span: 2;
  float-defer-column: 1;
}
Float figure to the top of the first column on the next-to-last page:
.figure { float: top }
.figure { float-defer-page: -1 }
Float figure to the top of the next-to-last column on the next-to-last page:
.figure { float: top }
.figure { float-defer-column: -1 }
.figure { float-defer-page: -1 }
last
The page float should be displayed in the last colum, or on the last page.
Float figure to the top of the last column on the natural page:
.figure { float: top }
.figure { float-defer-column: last }

sample rendering

Float figure to the last column on the last page:
.figure { float: top }
.figure { float-defer-column: last }
.figure { float-defer-page: last }
none
The page floats should appear in their natural column/page, if possible.

Zero is not a legal value.

6. Clearing page floats

Page floats may request to not be stacked, or to be the only page float on a page/column through new values on the clear property:

top/bottom
The page float requests to be the only page float at the top/bottom of the column. If there is already a page float at the requested position, the page float is moved to the next column which does not have a page float in the requested position.
column
The page float requests to be the only page float in the column. If there is already another page float on the page, the page float is moved to the next page which does not have a page float.
page
The page float requests to be the only page float on the page. If there is already another page float on the page, the page float is moved to the next page which does not have a page float.
In this example, the two figures may appear in the same column:
.figure { float: bottom; clear: none }

<div class=figure></div>
<div class=figure></div>

In this example, the two figures will appear in different columns:
.figure { float: bottom; clear: column }

<div class=figure></div>
<div class=figure></div>

In this example, the two figures may appear at the bottom of the same column due to clearing only at the top:
.figure { float: bottom; clear: top }

<div class=figure></div>
<div class=figure></div>

In this example, the two figures will appear in different columns due to clearing at the bottom:
.figure { float: bottom; clear: bottom }

<div class=figure></div>
<div class=figure></div>

In this example, the two figures end up the top corner of two different pages:
.figure { float: top; float-defer-column: last; clear: page }

<div class=figure></div>
<div class=figure></div>
In this example, the two figures request different positions, and they may therefore end up in the same column:
.figure.one { float: top; clear: top }
.figure.two { float: bottom; clear: bottom }

<div class="figure one"></div>
<div class="figure two"></div>

7. Floating inside and outside pages

Two allow content to flow to the inside and outside of a page, these keywords are added to the float property:

inside
On a right page, this value is synonymous with left. On a left page, this value is synonymous with right.
outside
On a left page, this value is synonymous with left, On a right page, this value is synonymous with right.

These new values do not create page floats, the are simply aliases for left and right.

.figure { float: outside }

Should there be a way to combine float: top/bottom with left/right?

Should there be a way to delete page floats that end up lonesome on pages?

8. Wrapping around page floats

Name: float-wrap
Value: none | wrap
Initial: none
Applies to: page floats
Inherited: no
Percentages: N/A
Media: visual
Computed value: specified value

This property indicates whether other content may wrap around a page float:

none
other content may not wrap around the page float
wrap
other content may wrap around the page float

The intrude value only works in combination with one of these keywords: left/right/top/bottom/top-corner/bottom-corner.

img { float: top; column-span: 2; float-wrap: wrap; width: 120%;  }

In this example, the image is wider than the column and will therefore intrude into the neighboring column. At the bottom of the middle column is a long word that is clipped in the middle of the column gap.

sample rendering

9. The float-offset property

Name: float-offset
Value: <length> <length> ?
Initial: 0 0
Applies to: floated elements
Inherited: no
Percentages: see prose
Media: visual, paged
Computed value: one or two absolute lengths

This property pushes a float in opposite direction of the where it has been floated with float. If one value is specified, it is the horizontal offset. If two values are specified, the first is the horizontal and the second is the vertical offset. If no vertical value has been specified, the vertical offset is set to zero.

This property can only influence a float along an axis it has been floated.

img {
  float: left;
  float-offset: 2em 3em;
}

In this example, the image is floated to the left. Therefore, float-offset may only push the element in the horizontal direction, and the vertical value is ignored.

Negative values are allowed; a negative values will push the float in the same direction as it has been floated with float

This property may move floats into other column than where they naturally appear.

img {  float: right;
  float-offset: 5px;
}

sample rendering

Percentage values are computed according to this formula:

(containing-block-width - float-width) * percentage
(containing-block-height - float-height) * percentage
Pull quotes are often centered in a column. In this example, the pull quote is floated to the right, and then pushed back into the center.

.pullquote {
  float: right;
  float-offset: 50%; /* 50% centers the box */
}

When negative values are set on this property, the column gap is also part of the calculation:

((containing-block-width + 2 * column-gap) - float-width) * percentage
img {  float: top right;
  float-offset: -50% 3em;  /* 50% centers the box */
  width: 120%;
}

sample rendering

img {
  float: top right;
  float-offset: -80% 2em;
  width: 100%;
}

sample rendering

10. Overconstrained page floats

In many cases, the specified values on these properties cannot be honored.

The number of columns is limited, and high values therefore cannot be honored:

.figure { float: top; float-defer-column: 1000 }
A narrow screen may only have room for one column, in which case this request cannot be honored:
.figure { float: top; float-defer-column: -5 }
In long documents, all content cannot fit on the last page, and this rule therefore cannot be honored:
p { float: top; float-defer-page: last }

Page floats are processed in the order they appear in the source. However, the visual order of page floats may not ne the same as the source order.

Consider this code:
.one { float: top; float-defer-page: last; column-span: all }
.two { float: top; clear: column }

<div class=one></div>
<div class=two></div>

In this example, the first element requests to appear on the last page, while the second element requests to appear in the natural column. If the natural column of the second element appears on a page before the last page, the second element will appear visually before the first.

Consider this code:

.one { float: top; float-defer-page: last; column-span: all }
.two { float: top; clear: column }

<div class=one></div>
<div class=two></div>

If all content can fit on one page, the first page will also be the last page. The first element is processed first and is placed on top of the first page. Then the second element is processed. It reqests a clear top, somthing which is not possible on the first page. Therefore, a second page is created and the first element is moved there. Even if the first element requests to be on the last page, it will not appear there.

When resolving over-constrained layouts, the order of importance for defined goals are:

  1. honor basic multi-column layout (columns, 'column-span: all', column-gap etc)
  2. honor 'column-span: <integer>'
  3. honor 'clear: top/bottom/pcolumn/page'
  4. honor float-defer-page
  5. honor float-defer-column
  6. honor 'float: top/bottom'
  7. display all content (as described by other CSS properties)
  8. keep the number of pages to a minimum

Changes

Changes from the 24 September 2013 CSS Page Floats Editor’s Draft:

  1. Removed sections on Regions and Exclusions
  2. Changed editor

Acknowledgments

This specification is made possible by input from Tab Atkins Jr., David Baron, Lars Erik Bolstad, Bert Bos, Mike Bremford, Michael Day, Werner Donné, Brady Duga, James Elmore, Elika Etemad, Michel Fortin, Daniel Glazman, Melinda Grant, Ian Hickson, Laurens Holst, Brad Kemper, Toru Kawakubo, Rune Lillesveen, Peter Linss, Cameron McCormack, Paul E. Merrell, Del Merritt, Markus Mielke, Kelly Miller, Alex Mogilevsky, Peter Moulder, Shinyu Murakami, Michel Onoff, Anton Prowse, Liam R E Quin, Jacob Grundtvig Refstrup, Florian Rivoal, Christian Roth, Allan Sandfeld Jensen, Simon Sapin, Morten Stenshorne, Philip Taylor, Ian Tindale, Ladd Van Tol, Tarquin (Mark) Wilton-Jones, Steve Zilles, Tantek Çelik and the CSS Working Group members.

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words "for example" or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word "Note" and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Advisements are normative sections styled to evoke special attention and are set apart from other normative text with <strong class="advisement">, like this: UAs MUST provide an accessible alternative.

Conformance classes

Conformance to this specification is defined for three conformance classes:

style sheet
A CSS style sheet.
renderer
A UA that interprets the semantics of a style sheet and renders documents that use them.
authoring tool
A UA that writes a style sheet.

A style sheet is conformant to this specification if all of its statements that use syntax defined in this module are valid according to the generic CSS grammar and the individual grammars of each feature defined in this module.

A renderer is conformant to this specification if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by this specification by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.)

An authoring tool is conformant to this specification if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module.

Partial implementations

So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers must treat as invalid (and ignore as appropriate) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents must not selectively ignore unsupported component values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.

Experimental implementations

To avoid clashes with future CSS features, the CSS2.1 specification reserves a prefixed syntax for proprietary and experimental extensions to CSS.

Prior to a specification reaching the Candidate Recommendation stage in the W3C process, all implementations of a CSS feature are considered experimental. The CSS Working Group recommends that implementations use a vendor-prefixed syntax for such features, including those in W3C Working Drafts. This avoids incompatibilities with future changes in the draft.

Non-experimental implementations

Once a specification reaches the Candidate Recommendation stage, non-experimental implementations are possible, and implementors should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec.

To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group.

Further information on submitting testcases and implementation reports can be found from on the CSS Working Group’s website at http://www.w3.org/Style/CSS/Test/. Questions should be directed to the public-css-testsuite@w3.org mailing list.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[CSS21]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 7 June 2011. W3C Recommendation. URL: http://www.w3.org/TR/2011/REC-CSS2-20110607
[CSS-MULTICOL-1]
CSS Multi-column Layout Module Level 1 URL: http://www.w3.org/TR/css3-multicol/
[CSS-PAGE-3]
CSS Paged Media Module Level 3 URL: http://www.w3.org/TR/css3-page/
[CSS-POSITION-3]
CSS Positioned Layout Module Level 3 URL: http://www.w3.org/TR/css3-positioning/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://tools.ietf.org/html/rfc2119

Property Index

Name Value Initial Applies to Inh. %ages Media Computed value
float-defer-column <integer> | last | none none page floats no N/A visual specified value
float-defer-page <integer> | last | none none page floats no N/A visual specified value
float-wrap none | wrap none page floats no N/A visual specified value
float-offset <length> <length> ? 0 0 floated elements no see prose visual, paged one or two absolute lengths

Issues Index

Do numeric values, to represent line numbers, make sense, like for orphans/widows?
An alternative way to express this would be to add a separate propertye, e.g., float-reference: column | multicol | page
Should there be a way to combine float: top/bottom with left/right?
Should there be a way to delete page floats that end up lonesome on pages?