W3C home > Mailing lists > Public > www-style@w3.org > June 2012

Re: Sticky Positioning

From: Brad Kemper <brad.kemper@gmail.com>
Date: Thu, 28 Jun 2012 17:09:27 -0700
Message-Id: <314C04FB-EEAA-4368-A71B-84EEEC2C9D5E@gmail.com>
Cc: Edward O'Connor <eoconnor@apple.com>, "www-style@w3.org" <www-style@w3.org>
To: Simon Fraser <smfr@me.com>
On Jun 28, 2012, at 11:16 AM, Simon Fraser <smfr@me.com> wrote:

>>> 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.
>> 
>> I think this would be great. But I don't think the tbrl keywords should be only be relative to the viewport, but rather to the nearest potentially scrollable ancestor (overflow: auto | scroll). In many designs that might be the main scrollable content area with the viewport itself not scrolling at all.
> 
> We've had others suggest this too.
> 
> A complication is that an ancestor may only be scrollable in one direction (overflow-y: scroll), so you may want to sticky-position on the Y axis relative to your overflow:scroll ancestor, and sticky-position on the X axis relative to the viewport. That's slightly crazy.

I think it would be enough to only have it relative to the scrollable ancestor, even if that ancestor only scrolled in one direction. Most of the use cases only involve sticking horizontally or vertically anyway, not both. So, supposing I had a vertically-only scrollable container that covered 90% of the page vertically, then it is really the vertical stickiness I care about. It is unlikely that I would also need it to stick to the side in case my vertical-scroll container was itself hidden by the viewport scrolling. Even if I did, supposing the sticky child had 'right:0', I'd be out of luck anyhow, because overflow-y: scroll on the container means that I will not be seeing the element outside the container as that container moved to the left with the viewport scrolling (overflow-x: visible will not make the child element visible outside the scrollable container).

>> I'm not sure what you mean by the containing box's edge, especially if you are talking about only the viewport being the measure of what the 'top: 10px' is relative to. Wouldn't it stop at the edge of the same box, ie the viewport?
> 
> The sticky element is positioned inside a box that is the intersection of the viewport (inset by the top/right/bottom/left values), and the containing block (inset by the sticky element's margins).
> 
> So the sticky element never escapes its containing block.

Ah, I understand now. That's interesting, once I wrap my head around it.

>> I would prefer that other position:sticky items (or perhaps sticky items with the same z-index) could push others out of the way, rather than overlap, in the way that list section labels do in iOS scrolling navigation lists (you know authors are going to want that). Thus is there are two items with 'top:0', the bottom one would push the top one out of the visible area until it could stick at 0 without overlap. Or if there are two items with 'left:0', the rightmost one would push the leftmost one off to the left. This is something important to have in first iteration, as it would be more clumsy to add it on later through a separate property, and I strongly suspect it will be the preferred mode.
> 
> We'd prefer to not do this initially. It adds enormous complexity. For example, do margins collapse between accumulating sticky-position elements? If so, it's very weird for margin-collapsing behavior to change as something starts acting stickily.

OK, it doesn't change whether or not the margins collapse, and authors can deal with that. Problem solved. Next?

Seriously, maybe I'm missing something. When it becomes sticky, it leaves behind an invisible placeholder with the same margins, right? So nothing changes in the layout there. If it normally had collapsible margins,then the sticky item still does, and those margins push against and collapse into the other sticky items on the z layer. Of course, if the author wanted the margins to go away when it became sticky, he could use a little JavaScript to change it, assuming there was an event to detect...

> You'd also have to specify how accumulating sticky-position things accumulate if they don't overlap on an axis.

They just stick if they don't overlap. I don't see the problem. If they only overlap on one axis, then they only push against each other in that direction. 

> I think it could get as complex as something like floats.

I hope not, though that does sound like a scary bogeyman.

> You can get the "pushing out of the way" behavior if you group your items in separate containing blocks.

That is an interesting idea. It seems like it would work for many of the use cases. But if it is the bottom of the container that finally pushes it out of sticking to the top, then the impression of something else (sticky) pushing it only works if that something is at the top of a container directly underneath it. This makes it a little more limited in power.

>>> 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.
>> 
>> I've no strong opinion on that, although it seems useful to have an event for sticking and unsticking, in case the author wants to change transparency or hide/show another element or something. You are doing away with all related events anyway, right? You still have scroll events, for instance.
> 
> I've also seen a suggestion that a pseudoclass be applied when an element is behaving stickily. Again, to preserve scrolling performance, I'd prefer to not do this or fire events.

Does it hurt it that much when it is just one event at the beginning or end of the stickiness? It seems like nothing compared the the fairly constant scroll events that take place at the binning, middle, and end of scrolling. What if the events only fired if there was an actual listener or pseudo-class present? Authors could just beware of the consequences of doing so, but it wouldn't be worse than using JavaScript like they do now, would it? It seems like a common need.
Received on Friday, 29 June 2012 00:10:02 GMT

This archive was generated by hypermail 2.3.1 : Tuesday, 26 March 2013 17:20:55 GMT