CSS Repeated Headers and Footers

A Collection of Interesting Ideas,

This version:
https://specs.rivoal.net/css-repeat/
Issue Tracking:
GitLab
Inline In Spec
Editor:
Florian Rivoal (Vivliostyle)

Abstract

CSS defines that table headers and footers are repeated when the table is fragmented. This specification defines a generalization of this mechanism, enabling authors to use it on elements other than tables.

1. Introduction

This section is non-normative.

A useful feature of the header and footer of [HTML] table has traditionally not fully been explain by CSS: when the table is fragmented across several pages or columns, the header and footer is repeated on each fragment.

[CSS2] and later [CSS-TABLES-3] have given some explanation about how this works, but do so by linking this behavior to the display type.

This specification instead explains it with a dedicated repeat-on-break property, and defines it in greater detail. It’s initial auto value triggers the legacy behavior of repeating the table header and footer, and setting it explicitly enables authors to get this effect on other elements, or to turn it off on table headers and footers where this is not desired.

Note: Fragmentation related behaviors, including repetition of table headers when fragmenting, have historically been better supported by print-oriented User Agents than by deskop or mobile browsers, as they attach greater importance to pagination. However, such features are by no means intended to be exclusive to print-oriented UAs, and support in browsers in encouraged.

1.1. Motivating scenarios

In no particular order, here are a few examples of situations where this property can be useful:

2. Module Interactions

This document allows authors to opt in or out of a behavior that previous specifications defined to apply to some elements (table headers and footers) only. It therefore replaces and supersedes the parts of previous specifications that defined this behavior:

Note: This specification is not intended to contradict the behavior described in [CSS-TABLES-3], only to generalize it. Leaving the repeat-on-break property at its initial value is expected to produce the same behavior as the one described in CSS Tables 3 §5.2 Repeating headers across pages. If it does not this should be considered an error in this document. If you notice any such problem, please report it.

3. Repeating elements: the repeat-on-break property

This property enables authors to designate one child of an element as the repeatable header and one as the repeatable footer of that element. If this element is fragmented, they will be repeated at the beginning and end of each fragment. Beforehand, the children of that parent are reordered to make the repeatable header and repeatable footer first and last.

Name: repeat-on-break
Value: auto | none | header | footer
Initial: auto
Applies to: Block-level elements, table-row-grouping elements, flex items, grid items
Inherited: No
Percentages: n/a
Media: visual
Computed value: See below for auto, as specified for other values
Canonical order: per grammar
Animation type: discrete

Values have the following meanings:

auto
The auto value computes to:
none
The element follows normal fragmentation rules, as defined in [CSS-BREAK-3]
header
The first child (in document order) of an element to have a computed value of header becomes the repeatable header of that element. header on subsequent siblings has no effect.
footer
The first child (in document order) of an element to have a computed value of footer becomes the repeatable footer of that element. footer on subsequent siblings has no effect.

An alternative approach would be to have the property apply to the parent rather than on the header and footer directly, and turn its first / last childern into a header / footer. The syntax would the become: auto | none | header || footer. This would simplify how this works by getting rid of reordering, and by reducing the amount of tree traversal needed to make this work. However, something else would then need to explain how the first table-header-group and table-footer-group get reordered, since they do have this behavior and it is currently underspecified. We would also need to define the interaction with the order property on flex items and grid items: presumably, just like with tables, we’d have to repeat the first/last child after reordering, which negates some of the tree traversal simplifications. Also, we would have to deal with situation where the first/last child of an elements are not Block-level elements, table-row-grouping elements, flex items, or grid items. Should we still reorder in that case, or should this make the property have no effect?

Add examples

3.1. Reordering

For the purpose of layout, if an element has a repeatable header child, that child is treated as if it was the first child of the element, and if it has a repeatable footer child, that child is treated as if it was the last child of the element. This also affects the painting order defined in CSS Flexbox 1 §4.3 Flex Item Z-Ordering for flex items, in CSS Grid Layout 1 §6.5 Z-axis Ordering: the z-index property for grid items, and in Appendix E of CSS2 for other elements.

For flex items and grid items, the effect is identical to that of the order property; repeatable headers behave is if they had the smallest order of all their siblings, repeatable footers as if they had the largest one.

This reordering does not affect ordering in non-visual media (such as speech), nor does it affect the default traversal order of sequential navigation modes (such as cycling through links, see e.g. tabindex [HTML5]).

This choice of affecting ordering only for layout and painting is for the sake of:

As with reordering using the order property, authors must only use header (resp. footer) on elements that are not the first (resp. last) child when the visual order needs to be out-of-sync with the speech and navigation order; otherwise the underlying document source should be reordered instead. See CSS Flexbox 1 §5.4.1 Reordering and Accessibility.

3.2. Repetition

If an element with a repeatable header is fragmented, the UA should repeat the repeatable header at the beginning of each fragment.

If an element with a repeatable footer is fragmented, the UA should repeat the repeatable footer at the end of each fragment, pushing content the next fragmentainer in the fragmentation context as necessary to make room for the repeatable footer.

Should this also apply to wrapped rows of a flex-wrap: wrap element in addition to fragmentation?

To account for the various rules and properties creating or suppressing break opportunities, to account for the prioritization of different classes of break-points, to avoid overflow or excessive fragmentation, or to strike an appropriate balance between performance and quality of layout, the UA may skip either or both of the repeatable header or the repeatable footer in some fragmentainers.

The exact algorithm to decide in with case to repeat or skip either or both of the repeatable header or the repeatable footer is up to the UA. However, the UA must guarantee progress through the content while ensuring that none of the content (including the repeatable header and footer) gets dropped. For that purpose, the algorithm must at least fulfil the following constraints:

In addition, in order to guarantee backwards compatibility with the behavior of tables in desktop browsers:

If

then

the repeatable header (resp. repeatable footer) must not be skipped.

A UA that would only include the repeatable header and repeatable footer at the beginning, the end, and the positions required for compability with the behavior of tables in desktop browsers and skip them everywhere else would not directly violate the above constraints. Such an implementation would not however be useful, as it would bring no new capability to authors other than reordering, which is merely a side effect, not the main point of this feature. Implementations which only support the repeat-on-break: none and repeat-on-break: auto values may limit themselves to this minimalist interpretation. However, implementations must not support the repeat-on-break: header and repeat-on-break: footer values without making the repeatable header and repeatable footer actually repeat with display types other than display: table-header-group and display: table-footer-group. While the flexibility given to implementors makes this difficult to assertain via formal tests, ignoring this requirement would make an implementation non-conforming.

Should we try to specify repeat/skip the algorithm instead of leaving it up to the UA? Should we leave it up to the UA but more constraints on it?

Apendix A. Security and Privacy Considerations

This appendix is non-normative.

There are no known security or privacy impacts of this feature.

The W3C TAG is developing a Self-Review Questionnaire: Security and Privacy for editors of specifications to informatively answer. As far as currently known, here are the answers to the Questions to Consider:

Does this specification deal with personally-identifiable information?
No
Does this specification deal with high-value data?
No.
Does this specification introduce new state for an origin that persists across browsing sessions?
No.
Does this specification expose any other data to an origin that it doesn’t currently have access to?
No.
Does this specification enable new script execution/loading mechanisms?
No.
Does this specification allow an origin access to a user’s location?
No.
Does this specification allow an origin access to sensors on a user’s device?
No.
Does this specification allow an origin access to aspects of a user’s local computing environment?
No.
Does this specification allow an origin access to other devices?
No.
Does this specification allow an origin some measure of control over a user agent’s native UI?
No.
Does this specification expose temporary identifiers to the web?
No.
Does this specification distinguish between behavior in first-party and third-party contexts?
No.
How should this specification work in the context of a user agent’s "incognito" mode?
No difference in behavior is expected or needed.
Does this specification persist data to a user’s local device?
No.
Does this specification have a "Security Considerations" and "Privacy Considerations" section?
Yes, this is the role of this Appendix.
Does this specification allow downgrading default security characteristics?
No.

Conformance

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.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[CSS-BREAK-3]
Rossen Atanassov; Elika Etemad. CSS Fragmentation Module Level 3. URL: https://drafts.csswg.org/css-break/
[CSS-DISPLAY-3]
Elika Etemad. CSS Display Module Level 3. URL: https://drafts.csswg.org/css-display/
[CSS-FLEXBOX-1]
Tab Atkins Jr.; Elika Etemad; Rossen Atanassov. CSS Flexible Box Layout Module Level 1. URL: https://drafts.csswg.org/css-flexbox/
[CSS-GRID-1]
Tab Atkins Jr.; Elika Etemad; Rossen Atanassov. CSS Grid Layout Module Level 1. URL: https://drafts.csswg.org/css-grid/
[CSS-PAGE-3]
CSS Paged Media Module Level 3 URL: https://drafts.csswg.org/css-page-3/
[CSS-PSEUDO-4]
Daniel Glazman; Elika Etemad; Alan Stearns. CSS Pseudo-Elements Module Level 4. URL: https://drafts.csswg.org/css-pseudo-4/
[CSS-TABLES-3]
Greg Whitworth. CSS Table Module Level 3. URL: https://drafts.csswg.org/css-tables-3/
[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 3. URL: https://drafts.csswg.org/css-values/
[CSS-WRITING-MODES-4]
CSS Writing Modes Module Level 4 URL: https://drafts.csswg.org/css-writing-modes-4/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[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

Informative References

[CSS2]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 7 June 2011. REC. URL: https://www.w3.org/TR/CSS2
[HTML5]
Ian Hickson; et al. HTML5. URL: https://www.w3.org/html/wg/drafts/html/master/

Property Index

Name Value Initial Applies to Inh. %ages Media Anim­ation type Canonical order Com­puted value
repeat-on-break auto | none | header | footer auto Block-level elements, table-row-grouping elements, flex items, grid items No n/a visual discrete per grammar See below for auto, as specified for other values

Issues Index

An alternative approach would be to have the property apply to the parent rather than on the header and footer directly, and turn its first / last childern into a header / footer. The syntax would the become: auto | none | header || footer. This would simplify how this works by getting rid of reordering, and by reducing the amount of tree traversal needed to make this work. However, something else would then need to explain how the first table-header-group and table-footer-group get reordered, since they do have this behavior and it is currently underspecified. We would also need to define the interaction with the order property on flex items and grid items: presumably, just like with tables, we’d have to repeat the first/last child after reordering, which negates some of the tree traversal simplifications. Also, we would have to deal with situation where the first/last child of an elements are not Block-level elements, table-row-grouping elements, flex items, or grid items. Should we still reorder in that case, or should this make the property have no effect?
Add examples
Should this also apply to wrapped rows of a flex-wrap: wrap element in addition to fragmentation?
Should we try to specify repeat/skip the algorithm instead of leaving it up to the UA? Should we leave it up to the UA but more constraints on it?