Sticky Positioning

Hi,

Many web sites have elements that alternate between being in-flow and
being position:fixed, depending on the user's scroll position. This is
often done for elements in a sidebar that the page author desires to be
always available as the user scrolls, but which slot into a space on the
page when scrolled to the top. It can also be done for table headers
which remain visible after the top of the table has been scrolled off-
screen.

Lots of sites, such as news.google.com (the "Top Stories" sidebar) and
yelp.com (the search results map), use scroll event listeners in
JavaScript to achive this effect. However, browsers are increasingly
moving towards scrolling implementations that make use of hardware
acceleration to improve performance, for example by leveraging the GPU,
and doing scrolling on a thread other than the main UI thread.

In this situation, browsers may use fast scrolling but fire scroll
events asynchronously, which will result in rendering glitches on pages
that update element positions from JavaScript via scroll events.
Alternatively, the browser may fall into a slow scrolling mode when
scroll events are listened for; this impacts the perceived quality of
the browser's scrolling. To address this problem, common scrolling
behaviors like this should be exposed declaratively, through CSS.

A feature like this has been a long time coming. It was first proposed
(for table headers) by the OEBPS (EPUB) folks on www-style in 2002[1]:

> One of the examples of the desired layout\formatting behavior would be
> that the header column would stay frozen if horizontal scrolling is
> required to view additional columns of the table (similar to the
> "Freeze Panes" option in Excel).

Mikko Rantalainen proposed generalizing such a feature to elements other
than table headers[2]:

> Perhaps a new position value (e.g. "fixed-relative") that is a mix of
> "relative" and "fixed": the content still reserves space in the flow
> similar to relative but it would be displayed as fixed if the element
> would not fit in the viewport but its containing block is visible. In
> that case, the element would be "moved" within its containing block
> until it would fully fit in the viewport.

Mikko's proposal is very close to what we have in mind: a new value for
the 'position' property, similar to relpos, but with a new method of
calculating the element's offset.

You'd use it like this:

h1 {
  position: sticky;
  top: 10px;
}

This means that every <h1> in the document will "stick" 10 pixels from
the viewport top when things scroll such that the <h1> would have been
partially off-screen. When the viewport has scrolled such that the
visible portion of the <h1>'s containing box is too small to fit the
<h1>, it should stop at the containing box's edge and only be partially
displayed.

There are a lot of details to work out, of course. Doug raised several
questions about such a feature in [3]; here are some preliminary
thoughts on them.

Doug wrote:
> * should sticky content accumulate?

No. In some future level of this feature, it might be worth
investigating a new property or set of properties which could cause such
accumulation. We should avoid this problem in the first level of this
feature by having the sticky elements simply overlap, just as other
positioned elements do.

Doug wrote:
> * what should be the behavior when a user jumps to the middle of a
>   containing block that would otherwise have a sticky header/footer
>   when scrolled (e.g. a row in the middle of a very long table, a
>   paragraph under a sticky <h2> itself under a sticky <h1>)? (I think
>   it the sticky content effect should be applied, though I suspect
>   this will make implementation rather more difficult.)

The sticky effect should be applied, just like any other positioning
scheme.

Doug wrote:
> * should there be an event that is thrown when content sticks, so
>   that the author can choose to enhance the effect via script or
>   declarative animation?

No. A big advantage of this feature over emulations of it in JS is the
lack of events.


Thanks,
Ted

1. http://lists.w3.org/Archives/Public/www-style/2002May/0153.html
2. http://lists.w3.org/Archives/Public/www-style/2009Dec/0165.html
3. http://lists.w3.org/Archives/Public/www-style/2009Dec/0204.html

Received on Tuesday, 26 June 2012 23:51:21 UTC