W3C home > Mailing lists > Public > www-style@w3.org > December 2009

Re: Proposal: Fixed Table Headers in CSS

From: Brad Kemper <brad.kemper@gmail.com>
Date: Tue, 15 Dec 2009 14:17:55 -0800
Message-Id: <F1759B32-9847-4DFD-BADB-D0574D03EB1A@gmail.com>
To: "Tab Atkins Jr." <jackalmage@gmail.com>
Cc: Doug Schepers <schepers@w3.org>, "Eric A. Meyer" <eric@meyerweb.com>, Mikko Rantalainen <mikko.rantalainen@peda.net>, www-style CSS <www-style@w3.org>


On Dec 15, 2009, at 11:19 AM, "Tab Atkins Jr." <jackalmage@gmail.com>  
wrote:

> On Tue, Dec 15, 2009 at 12:47 PM, Brad Kemper  
> <brad.kemper@gmail.com> wrote:
>> On Dec 15, 2009, at 6:06 AM, Tab Atkins Jr. wrote:
>>> Note, though,
>>> that putting it on both a header and footer means that they'll  
>>> both be
>>> visible at all times while the table is visible.  They'll appear
>>> first, then they'll separate and show the data.
>>
>> Assuming the table fit within the viewport, they would appear  
>> normally at first. Then when the thead reached the top it would  
>> look like it was fixed. Eventually the tfoot would scroll up to  
>> touch the bottom of the thead. The same thing would happen in  
>> reverse when scrolling down instead of up, with the tfoot becoming  
>> fixed at the bottom of the viewport.
>
> Yes.  However, if the table is, say, one screen-height tall, and
> starts off halfway down the screen, then both the thead and tfoot
> would appear on-screen immediately, with some of the table between
> them.  As you scrolled down the thead would raise and the tfoot would
> stay at the bottom of the screen, until the bottom of the table is
> visible.

Right. Then as you continue to scroll down past the table, the tfoot  
would scroll up to the thead until there was nothing between them, and  
then push the thead off the top. This is assuming 'thead { top:0; }'  
and 'tfoot { bottom:0; }'.

The 'top' measurement is really then the minimum distance from the top  
of the viewport (or other containing block, if that block is  
positioned or scrollable) that the element can be scrolled to, until  
something else (the bottom of it's container, or another sticky-top  
element) pushes it off the top of the screen.

>
>> The iPhone interface for such iPhone apps as "Contacts" solves this  
>> very neatly. The sticky content does not accumulate within the  
>> viewport, but instead gets pushed off-screen when other sticky  
>> content scrolls up to meet it. If you are not familiar with this  
>> iPhone convention, then first take a look at this jQuery-based demo  
>> I found on the Web:
>
> Indeed.  If things are sticky relative to their containing block, then
> the iPhone Contacts app would be coded with each group of contacts
> being a containing block for the sticky heading.  They don't
> accumulate because as each heading reaches the top, the bottom of the
> previous containing block also approaches the top of the screen, which
> will push the previous heading out-of-view with it.
>
>> My idea is that this would be a position property, such as  
>> 'position: sticky' or 'position: scroll-limited' or 'position: semi- 
>> fixed'. And thus, it would use 'top', 'bottom', 'right', and 'left'  
>> properties, in this case to determine where within the viewport (or  
>> within the containing block) the element would "stick" and become  
>> semi-fixed, relative to that side. Thus, for a table header, you  
>> might have this:
>>
>> thead { position: scroll-limited; top:0; }
>>
>> Or, suppose you already had a position:fixed page header that was  
>> 100px tall, and you wanted the table headers to stop below that  
>> when scrolling, along with a little extra room:
>>
>> #page-header { postion: fixed; top:0; height: 100px; }
>> thead { position: scroll-limited; top: 110px; }
>>
>> The thead would stay fixed at the 'top' value for as long as it's  
>> "natural" scroll position would be that number or less relative to  
>> the top of the scroll port. Once it became more than that number,  
>> it would assume normal scrolling (like position:static).
>>
>> You could also get items to stick to the bottom this way, when they  
>> would ordinarily be scrolled off-screen:
>>
>> tfoot { position: scroll-limited; bottom:0; }
>>
>> Or you could use the 'left' or 'right' properties to get columns  
>> (or, more likely, THs within a column) to stick in place  
>> horizontally.
>>
>> So... items wouldn't really accumulate around the edges of the  
>> viewport because they get pushed offscreen by elements that also  
>> have the same edge set. If two elements, a 'top' and a 'bottom' for  
>> instance, did not fit in the same viewport, then they would be  
>> pushed outward from where they touch (and you wouldn't see anything  
>> that was between them).
>
> That's an elegant way to handle it, and I like it.  I'm not sure what
> you mean in the last paragraph, though.

Its kind of a thought expirimdnt, and I've just thought some more...  
So, let's say the height of thead was 60% of the viewport height, and  
so was the tfoot. Then they can't both fit completely onscreen  
together, and some part will be offscreen, depending on how far down  
you scroll. Really, you'd see the complete thead first when you scroll  
down to it, then the complete tfoot when you scroll a little more. I  
think eventually you'd want to see what's in between also, so perhaps  
either the thead or tfoot (depending on scroll direction) would still  
get pushed offscreen enough to see at least one line of text or one  
table-row or by the min-height of what's in between in this situation.

> Can you explain what it means
> in terms of an example, like how the following code would work?
>
> <h1>Foo</h1>
> <p>foo foo foo</p>
> <h2>Bar</h2>
> <p>bar bar bar</p>
> <h2>Baz</h2>
> <p>baz baz baz</p>
> <style>
> h1,h2 { position: sticky; top: 0; }
> </style>
>
> In my conception, these should all accumulate, since they all have the
> same containing block (<body>) and sticky boxes aren't allowed to
> overlap.  In order to get them to accumulate in the way you would
> expect, you'd instead do:
>
> <h1>Foo</h1>
> <p>foo foo foo</p>
> <section>
>  <h2>Bar</h2>
>  <p>bar bar bar</p>
> </section>
> <section>
>  <h2>Baz</h2>
>  <p>baz baz baz</p>
> </section>
> <style>
> h1,h2 { position: sticky; top: 0; }
> section { position: relative; }
>
> This way the <h1> stays on the screen at all times, as it's sticky
> relative to <body>, but the <h2>s only stay on the screen as long as
> their containing <section> does, and so will *appear* to displace each
> other as the <section>s scroll on or off of the screen.
>
> How would each of these examples work in the way you're envisioning  
> things?

At any one time, only one element would be "stuck" to its top  
position. The first H2 would push the H1 off the top of the screen  
when you scrolled it up high enough.

I see what you mean now about accumulating. You don't want the H2 to  
push the h1 in it's grandparent off, right? But I don't see how you  
prevent that if the 'top' of the H2 is relative to the offscreen top  
of the section. You could do something like the following to prevent  
the H1 from being pushed off:

h1 { position: sticky; top: 0; }
h2 { position: sticky; top: 2am; }

>
Received on Tuesday, 15 December 2009 22:18:41 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Tuesday, 22 May 2012 03:47:12 GMT