[csswg-drafts] [css-position] ‘Sticky’ as position scheme that uses containing block and margin is too limiting?

jonjohnjohnson has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-position] ‘Sticky’ as position scheme that uses containing block and margin is too limiting? ==
https://drafts.csswg.org/css-position-3/#sticky-pos

_TLDR_ Should sticky be it's own property that sets edge and distances within it's offset parent instead of it's containing block?

I know that "sticky" behavior has already landed in all major browsers, buuuut I'm still gonna lay out how it confuses me after putting it through the ringer.

### Rehashing Sticky

When something is "sticky" it boils down to these bits...
1. Scrolling context
2. Box to stick within inside scrolling context
3. Sticky edge
4. Distance from sticky edge
5. Distance from box's opposite edge to stop sticking.

After setting an element as `position: sticky` those bits are gathered in these ways...
1. Nearest ancestor scrolling in the axis of of sticky edge (bar any ancestors between element and scroll context set with `overflow` incompatibilities).
2. Elements containing block (often defined by parent element, though ancestors between the element and it's containing block could have `inline` layouts with `position: relative` and valid box offsets).
3. Any box offset not computed as `auto`, such as `bottom: 0px`.
4. The value of the that set box offset.
5. Computed from both the margin of the element on the opposite edge to which is sticking AND the opposite edge of it's containing block.

### Issue 1 -  Duo implication of margin?
The easiest issue to spot with this is mixing the use of margin for both normal flow AND the "sticky constraint rectangle". It’s use for "SCR" in any meaningful way forces an author to offset that margin in normal flow with a sibling element, getting nice and hacky.

##### EXP Bottom sticky flag that's hidden in the fold, but scrolls in just after
```css
.flag { position: sticky; bottom: 0px; margin-top: 100vh; }
.before-flag { margin-bottom: -100vh; }
```
##### EXP Nested lists with sticky headers/labels
```css
.label { position: sticky; top: 0px; margin-bottom: var(--height-label); }
.after-label  { margin-top: calc(-1 * var(--height-label)) }
.label-nested { position: sticky; top: var(--height-label); }
```
So why not gather this length in a different way? Similarly to why `scroll-margin` was created to not just infer or force *hacky layouts for an author to fully leverage snapping?

### Issue 2 - Use of containing block?
Some aspects of layout require particular structures (like what's shown in this spec), so using the elements containing block instead of allowing authors more control over the creation of a "sticky constraint rectangle", has major tradeoffs.
> It's actually hard to get this behavior otherwise as if you wrap a box around the sticky element for an anchor it will contain it and prevent the sticky element from moving.(https://github.com/w3c/csswg-drafts/issues/1459)

I'd imagine using an elements offset parent would give more control to an author instead of using it's containing block? Or at least using the offset parent until reaching the scrollport, then using that scrollbox.

### Issue 3 - Other position schemes would be useful?
When we are already limited to the use of containing block for "SCR", it's worse that we can't even use another position scheme to move the element around within it's containing block. Not allowing for these position schemes, can force an author to sacrifice semantic order, when trying to place an element in a desired normal flow to then "stick" based upon that shifted position. Think of simply sliding an element around "relatively" or even "absolutely" pushing an element to the bottom side of it's offset parent to then "stick" off the bottom scrollport edge, when semantically the element isn't at the end of the sequence). And creating a hacky flex/order/margins solutions doesn't fix the issues that come with not having access to relative/absolute position schemes.

Again, why not use an elements offset parent instead of it’s containing block? Then allowing the sticky element to still leverage relative or absolute schemes for itself? I'd say even forcing that sticky behavior can only be applied to a positioned element in the first place, like how box offsets require position. Caveat being that fixed position affords no sticky affect.

### Solution for all 3 issues?
In my understanding the information needed to set up sticky behavior (as well as proper optimizations, so one doesn’t need to set isolation or will-change, like is often needed now) is better suited from a separate property (not creating a position scheme) such as...
```css
sticky: bottom 40px 100vh;
sticky: top 0px 50px, left 0px 50px;
```
A property where you could set a list of sticky edges, with their corresponding sticky start distance AND end distance (from opposite edge to be passed sticking). If just the start is set, then lengths are computed as `0`? If only the start is set, the end computes to `0` which is surely the most common case. For the property to have any affect the element must be positioned and it uses the containing block of it's offset parent as reference to create a "SCR" instead of it's own containing block. I've scraped through the spec and created an assortment of experiments leveraging sticky-ness and it seems like what I'm proposing (though most likely far too late to ever be considered) would be viable.

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/2496 using your GitHub account

Received on Tuesday, 3 April 2018 17:50:31 UTC