A proposal for implementing footnotes and other features

Introduction

This all came about because I started to think about about how to handle footnotes. I actually had gotten to the point where I was about to make a post to www-style back in February with a proposal. Then I realized how it might be generalized with only a few changes to my original idea. Those changes yielded increased functionality beyond just footnotes. Just when I was about ready to post again, Ian gave us a hint of what was to come with the CSS3 Generated and Replaced Content Module. Now that the working draft has been released, and I’ve had time to digest it, I’m ready to present my proposal.

You will find herein both the bare bones of my proposal as well as examples of how it could be used. Examples include endnotes, footnotes, a table of contents, and for lack of a better term: sticky notes. The basic functionality has been gained by adding values to existing CSS2 properties. Two new properties and eleven new pseudoelements are provided to provide fine-grained control of the presention.

What this proposal is not

This propoosal is not an alternative to the CSS3 Generated and Replaced Content Module. For one thing, many things that it does are not addressed in this proposal. While both address the issue of the footnotes, they do so in different ways and with different agendas.

What this proposal is

This proposal provides two basic mechanisms: referrals and context lists. Referrals are a method of transferring the content of one element to another element. Context Lists are a method of displaying referred content only when its reference point is in the current viewport.

Referrals

The central idea here is that there ought to be a way for an element to be in two places at once. To handle footnotes properly requires a mechanism to connect the footnote reference and the footnote itself. This requires affecting the document flow and changing it from being the same as the document structure. In plain HTML without any CSS, the document flow and the document structure are one and the same. In CSS 1, the display property allowed an element to be removed from the document flow. Begining with CSS 2, the position property allowed for changes to the document flow beyond removal. Referrals add a mechanism to attach the flow of an element onto that of another element as if it were a child element of that other element.

The ::nth-referral(an+b) pseudo-element

Name: ::nth-referral(an+b)
Initial Content: The content of an element attached to the parent element thru the use of the referral(x) function.
Applies to: All elements that are the target of a referral(x) function.
Initial CSS values: Those of the attached element except for the position property which is changed to relative. (See the description of the referral(x) function for details.)

See the :nth-child(an+b) pseduo-class for a details on how the argument works. This pseudo-element selects from the elements attached to the parent element. For example ::nth-referral(3n) matches the content from every third appendage of any element.

The ::nth-last-referral(an+b) pseudo-element

This is to ::nth-referral(an+b) as :nth-last-child(an+b) is to :nth-child(an+b).

The ::first-referral pseudo-element

This is to ::nth-referral(an+b) as :first-child is to :nth-child(an+b).

The ::last-referral pseudo-element

This is to ::nth-referral(an+b) as :last-child is to :nth-child(an+b).

The ::only-referral pseudo-element

This is to ::nth-referral(an+b) as :only-child is to :nth-child(an+b).

The ::reference pseudo-element

Name: ::reference
Initial Content: If the display-role of the parent element is list-item, then the initial content is that of the ::marker pseudo-element. Otherwise, the initial content is empty.
Applies to: All elements with a position of referral(x).
Initial CSS values: Same as parent except for display-model, display-role, and position .
display-model inline-inside
display-role inline
position static

The ::reference pseduo-element is the content that is left behind in the location in the normal flow where the element would have been had its position been static.

The reference-index property

Name: reference-index
Value: <integer>
Initial: 0
Applies to: All elements with a position of referral(x).
Inherited: no
Percentages: N/A
Media: All
Computed value: specified value (except for initial and inherit)

The reference-index property is used to specify the order that elements attached to another via a position of referral(x) are appended. An attached element with a reference-index of 0 is appended last. All other attached elements are appended in the order of their reference-index beginning with the lowest reference-index. If multiple elements are attached to the same element, the order of appending is the same as their occurence in the document.

The reference-link property

Name: reference-link
Value: none | both | to-ref | from-ref
Initial: none
Applies to: All elements with a position of referral(x).
Inherited: no
Percentages: N/A
Media: Any interactive media
Computed value: specified value (except for initial and inherit)

This property controls the creation of links between an element and its ::reference pseudo-element.

If the value of this property is both or to-ref, then a DOMActivate event reaching the element on the bubbling phase causes the viewport of the document to change (if necessary) to place the ::reference pseudo-element in the viewport. The event is not propogated further.

If the value of this property is both or from-ref then a DOMActivate event reaching the ::reference pseudo-element on the bubbling phase causes the viewport of the document change (if necessary) to place the element in the viewport. The event is not propogated further.

If a user agent supports XHTML hyperlinks, then the method(s) of causing the DOMActivate event to be triggered should be the same as the method(s) activating a hyperlink in XHTML.

The referral(x) function

Name: referral(x)
Argument: <idref> | attr(x)
Applies to: The position property of any element (but not any pseudo-element).

This function is added to the allowable values of the position property. The argument of the referral(x) function should resolve to an IDREF as defined in XML. It can either be given directly, or it can be an attribute specified by the attr(x) function. (Note: It is not a requirement that the attribute be of type IDREF.) If the ID referenced by the argument of the referral(x) function is not present in the document, then the rule should be considered invalid and ignored.

Here is what happens when the rule is valid:
[1] The element and all of its children is removed from the normal flow.
[2] The ::reference pseduo-element associated with the element is placed into the normal flow in place of the element and its children.
[3] The content of the element is appended to the element specified by the argument of the referral(x) function, as if it were a child of that element with a position property of relative.
[4] If the contents of multiple elements are appended to the same element, then they are appended in the order described in definition of the reference-index property.

Note that it is possible for an infinite loop of links to be established via the referral(x) function. User agents implementing referral(x) must be able to detect such loops and stop them. All such elements are effectively removed from the document flow and are not displayed. This is equivalent to all of them having a display value of none, except that the ::reference pseudo-elements are still part of the document flow. User agents implementing references may provide a mechanism, whereby the content of elements removed from the document flow because of such infinite links can be accessed. User agents that implement the reference-link property should have the method used to link from the ::reference pseudo-element provide access to the parent element if they provide any access.

Context Lists

For such things as endnotes or a table of contents, referrals as defined above are sufficient. However, to implement footnotes, it is necessary to also have a methos of only showing the referrals whose ::reference pseudo-elements are in the current viewport or page, and a mechanism for dealing with the overflow if the chosen area is unable to show all the referrals. I call the method presented here context lists, altho I’d gladly entertain any idea for a better name.

To properly implement footnotes, I also found it necessary to add additional value to the overflow property.

The context-list value

Name: context-list
Applies to: The display and display-role properties of any element (but not any pseudo-element).

The CSS rule display:context-list is shorthand for the CSS rules display-model:block-inside and display-role:context-list.

The CSS rule display-role:context-list is similar to the CSS rule display-role:list except that only some of the referrals are visible. The referrals that are to be visible are those whose ::reference pseudo-element are displayed in the current viewport.

The ::nth-context(an+b) pseudo-element

Name: ::nth-context(an+b)
Initial Content: The content of an element attached to the parent element thru the use of the referral(x) function.
Applies to: All elements that are the target of a referral(x) function.
Initial CSS values: Those of the attached element except for the position property which is changed to relative. (See the description of the referral(x) function for details.)

See the :nth-child(an+b) pseduo-class for a details on how the argument works.

If the parent element has a display-role of context-list, this pseudo-element selects from the elements attached to the parent element which have a ::reference pseudo-element displayed in the current viewport. In the case of paged media, the viewport is the page and it is possible that attached elements will overflow to the next page. In such a case, ::nth-context(1) refers to the first attached element displayed on the current page, even if it has overflowed from a previous page.

If the parent element does not have a display-role of context-list, then ::nth-context(an+b) is equivalent to ::nth-referral(an+b).

The ::nth-last-context(an+b) pseudo-element

This is to ::nth-context(an+b) as :nth-last-child(an+b) is to :nth-child(an+b).

The ::first-context pseudo-element

This is to ::nth-context(an+b) as :first-child is to :nth-child(an+b).

The ::last-context pseudo-element

This is to ::nth-context(an+b) as :last-child is to :nth-child(an+b).

The ::only-context pseudo-element

This is to ::nth-context(an+b) as :only-child is to :nth-child(an+b).

The page-break value

Name: page-break
Applies to: The overflow and overflow-y properties of any element.

The CSS rule overflow:page-break is shorthand for the pair of CSS rules overflow-x:initial and overflow-y:page-break.

In most circumstances overflow-y:page-break has the same effect as overflow-y:scroll. The only difference in behavior occurs when the element has position:fixed and the medium is a paged media. In that case, any overflow is sent to the same containing box, but on the next page.

Note that the traditional behavior that occurs when printing XHTML documents can be expressed via the CSS rule set body {overflow-y:page-break}. This is a serendipitous side effect of adding this value.

Examples

Here I intended to give five examples, showing how in theory, endnotes, section notes, footnotes, a table of contents and sticky notes could be implemented using the ideas in this proposal. However, I onl;y have one example, the simplest one, endnotes, done. Since the Generated and Replaced Content Module has come out, I had the problem do I send this out now, or do I wait until I have my examples all done. I chose to send out what I already had available.

Common features of all examples

Several HTML examples are given below to demonstrate how this proposal works. All will use the following style sheet common.css:

.cl {display:context-list}
.ref {
 display:list-item;
 list-style-type:numeric;
}
All output will be displayed in boxes like the following:
 

Endnotes

This is the simplest of the five examples and hence is the one I’ve chosen to present first.

Here is the code for the example:

<html><head>
 <title>Endnote Example</title>
 <link> rel="Stylesheet" href="common.css">
 <style>
  .ref {position:referral(endnotes)}
 </style>
</head><body>
 <h1>Endnote Example</h1>
 <p>
  Blah blah blah blah blah.
  Bleh Bleh bleh bleh bleh.<b class="ref">Blih Blih.</b>
  Bloh Bloh bloh bloh bloh.<i class="ref">Bluh Bluh.</i>
 </p>
 <div id="endnotes">
  Endnotes
 </div>
</body></html>
And here is the output:

Endnote Example

Blah blah blah blah blah. Bleh Bleh bleh bleh bleh,1. Bloh Bloh bloh bloh bloh.2.

Endnotes
  1. Blih Blih.
  2. Bluh Bluh.

Questions and issues

  1. Are the sticky notes really necessary, or am I trying too hard to come up with a use for looped referrals?
  2. I've defined ::nth-referral(an+<b and related pseudo-elements to enable fine tuned access to the referrals. Are they really needed or is there a simpler way of providing styling based on the order in which content is appended?
  3. Is the reference-index property really needed? It's simple enough to define, but I haven't been able to come up with a good use case for it. I don't need it for any of my examples.
  4. Can this idea be adapted to make use of the move-to property in the Generated and Replaced Content Module working draft?
  5. I think that the idea I like most here is the context list, as it allows for fluid footnotes. (i.e. the only footnotes shown are those referred to in the current viewport.) It seems to me that the way the Generated and Replaced Content Module works, it doesn't have that capability except for paged media.