Re: [css-sticky-scrollbars] feedback and variations on the concept

On Mon, Jun 29, 2015 at 5:10 PM Florian Rivoal <florian@rivoal.net> wrote:

> Hi Tab,
>
> I've been looking at this proposal of yours
> discussed in https://tabatkins.github.io/specs/css-sticky-scrollbars/
>
> I think it is overall a good idea addressing valid use cases, but I have
> some
> disagreements about the design, so I've been thinking of how to tweak it
> to be
> more to my liking. Also I have some use-cases that are not explicitely
> addressed by your proposal which should be covered as well.
>
> If you just want my proposal, jump all the way to the bottom of this mail,
> to
> SUMMARY. Otherwise keep on reading for the rationale building up to that
> proposal.
>
> == FULL STORY ==
>
> First, I am not sure that anchoring at a distance from the edge is what we
> actualy
> need. I absolutely see that in in the chat example, if you're in the
> middle of
> the scroller, you want to stay there no matter how much content gets added
> to
> the end. But if you scroll to 1em of the end, with a scroll-anchor
> distance of
> 2em, do you want to stay forever at 1em from the end? You might fail to
> notice
> and forever miss one line as new messages get added. It seems to me it
> would be
> more friendly to snap to the end, and anchor there. Maybe both are useful
> and we
> can have a switch, but if we only get one, I think it should be the one
> that gets
> you to the edge, not the one that keeps you near it.
>
> Also if you're not within the scroll-anchor distance from the edge, and the
> content grows, it would be useful to be able to say from which edge of the
> scroller you maintain a constant distance. In the classical chat example,
> or
> similar situations where content gets added to the bottom, you want to
> maintain the offset from the top. But when new content comes at the top,
> as it does for example in twitter, you want the other way around.
>
> This, together with the "go-to-the-edge-if-you-are-close" behavior mean
> that
> specifying the behavior both on the start and end edge are useful. Under
> your
> proposal only one side (start or end) per axis can have an anchor zone.
>
> With names to be bikesheded, that gives me the following properties
> instead of
> overflow-anchor.
>
>  scroll-offset-anchor: [ start | end ]{1,2}
>  scroll-edge-behavior: [ inert | [ glue | magnet ] <length>? ]#{1,4}
> or maybe
>  scroll-edge-behavior: inert | [ glue | magnet ] <length>{0,4}
> if the previous one is overkill
>
> scroll-offset-anchor tells you if you maintaint the distance from the
> start or
> end edge of the scroller when it grows and you're somewhere in the middle.
> If
> you have 1 value, it applies in the inline and block directions, and if you
> have 2, the first is block and the second is inline.
>
> scroll-edge-behavior is similar to your overflow-anchor, and tells you what
> happens if you get within the scroll-anchoring distance of an edge.
> ''inert''
> get you what we have now without any special property, ''glue'' what you
> specified, and ''magnet'' scrolls you all the way in. The optional length
> works the same as in your spec to set the scroll anchoring distance. If you
> set 1 value, it applies to all 4 edges, and 2 to 4 values work the usual
> way:
> top-bottom left-right, top left-right bottom, top right bottom left.
>
> Another consideration is that if instead of manual scrolling (scrollbar,
> mousewheel, touchscreen...), what is trigering the scrolling is moving the
> text insersion caret inside a editable text field, it's a bit more tricky.
> Let's say your scroll-anchoring distance is equivalent to 3 lines' height.
> At
> any point in the editable field other than the last 3 lines, if you move
> the
> caret down one line and that line was the last visible line, your scroller
> moves by 1 line.  If you move to caret to the 3rd-to-last line and we're in
> glue mode, nothing special happens, since caret movements explicitly change
> the scroll position. In magnet mode though, we jump all the way to the
> edge,
> which may be jarring. What we could do instead is always mainting a
> scroll-anchoring distance worth of space between the caret and the visible
> edge of the scroller. That way, when you're within the last 3 lines, the
> result is the same and you're scrolled all the way, but this happens
> without
> discontinuity in the amount of scrolling you get when you move the caret by
> one line.
>
> It also seems that this "keep a bit of context around the caret" effect can
> also be quite useful even if we're not anchoring at the edge, so maybe it
> should be a separate property. This is not an essential part of the
> proposal,
> but it seems better to me with it.
>
> scroll-context: auto | <length>{1,4}
>
> auto gets the value from the scroll-anchoring distance (maybe only in
> magnet
> mode?), the other values let you set it up explicitely.
>
> Besides caret based scrolling, this could also apply to scrolling
> triggered by
> focusing elements. If you focus (by pressing the tab key,
> programatically...)
> a button or something that is in the scroller, but out of view, the scroll
> offset is adjusted to make it visible. So far so good. But if you have for
> example a 15px box shadow around your buttons that you would like to be
> visible when focusing them, you could set "scroll-context: 15px" to make
> sure
> the whole thing is in view. Which makes me think that maybe scroll-context
> should also apply to focusable children of the scroller, to let you
> override element by element the values set on the scroller itself.
>
> == Demos ==
> Here are a few JS-bins to play around with. They illustrates situations
> other
> than the chat or twitter examples when these properties would help.
>
> * Demo 1
> http://output.jsbin.com/xovuzil/
>
> Problems with a scroller with padding that contains an editable thing, and
> an
> overlay over the scroller meant to fit in the padding when you're scrolled
> all
> the way down.
>
> Would be made better with either "scroll-context: 1em" directly, or
> getting it
> through "scroll-edge-behavior: magnet 1em".
>
> * Demo 2
> http://output.jsbin.com/mabemi/
>
> Similar to demo 1, except the padding overlay is in the scroller instead of
> over it.
>
> Would also be made better with either scroll-context or
> scroll-edge-behavior:magnet, potentially with different values on different
> edges. (scroll-edge-behavior: magnet 1em, magnet 1em, magnet 2em).
>
> In these 2 examples, glue mode (or equivalently, the overflow-anchor
> behavior)
> wouldn't help: if you have scrolled all the way down, and type text to
> grow the
> content, the caret movements will set the scroll position, overriding the
> glue
> effect. While the caret would be kept in the visible area of the scroller,
> it would not account for the overlays, which would move out of view in
> demo 2,
> or obscure the content in demo 1.
>
> * Demo 3
> http://output.jsbin.com/fusedo/
>
> This one is arguably less disfunctional than the first 2, but may suffers
> from hidden content if you navigate the content of the scroller by tabing
> around instead of scrolling around, depending on exactly how the UA choses
> to
> bring the focused element into view. (On this example, webkit/blink do well
> even without the property, but Firefox and IE do not).
>
> This also would benefit from using either properties, in the same way the
> preceding 2 examples did.
>
> In all 3 demos, if you don't expect the content to be programatically
> grown,
> using either property gets you the same thing, but if you do, using
> scroll-edge-behavior is likely preferable.
>
> == SUMMARY ==
> Replace overflow-anchor by scroll-edge-behavior, and add
> scroll-offset-anchor
> and scroll-context.
>
> scroll-edge-behavior: [ inert | [ glue | magnet ] <length>? ]#{1,4}
> or
> scroll-edge-behavior: inert | [ glue | magnet ] <length>{0,4}
> Initial: inert
> Applies to: scrollable elements
> Definition: sets up scroll-anchor areas, and the behavior in them: stay
> where
>             you are, or scroll to the edge and stay there.
>
> scroll-offset-anchor: [ start | end ]{1,2}
> Initial: start
> Applies to: scrollable elements
> Definition: From which edge of the scroller should the distance be
> maintained
>             the scroller grows if we're not in a scroll-anchor area.
>
> scroll-context: auto | <length>{1,4}
> Initial: auto
> Applies to: Scrollable elements and focusable descendants of scrollable
>             elements
> Definition: When the scroll position is moved by caret movements or by
>             focusing elements, how much room should be kept between this
>             active element and the visible edges of the scroller. auto
>             computes to the scroll-anchor distance of magnet-mode edges.
>
>
>  - Florian
>
>
I wonder if  there been any attempt to see if the same properties can be
achieved using css scroll snap points. This specs is trying to provide a
mechanism to control how scroll position is maintained when an scrolling
element is resized[1]. Snap points spec has a similar mechanism where
the scrolling
container scroll offset remains at the snap point location after resize[2].

I think with some minor changes to the css snap points specification it
should be possible to implement scroll-anchors using proximity snap points
at appropriate edges of the scrolling area. I think we need these changes:


   1. A way to specify snap points at the start and end of the container.
   There is already an issue
   <http://dev.w3.org/csswg/css-snappoints/#issue-1011500c> in the spec to
   add something like this.
   2. scroll-anchor spec allows specifying the distance from which the
   anchoring comes into effect. Proximity snap points do not expose this but
   there is not reason why they shouldn't. For example something like
   scroll-snap-type: proximity 100px; can work well.
   3. Remaining at snap point after resize is mandatory only for mandatory
   snap points but optional for proximity ones. Perhaps this can be changed to
   make maintaining snap position after resize mandatory in both cases. (or
   expose separate snap types for user input scrolls and resize related
   scrolls)
   4. Florian's suggested modifications propose having different modes of
   anchoring such as glue or magnet. I think this can be achieved by having
   more extensive options for proximity snapping. The bonus is that these work
   the same for anchoring and other snapping behavior.

If we make these changes the following should work the same as the example
in the spec. If the user is scrolled to the bottom (i.e. snapped) the
container maintains its bottom scroll offset and reveals new message as
they come in. At the same time allows user to scroll freely in the middle
without any scrolling distraction from "auto-scroll" behaviour.

.chat-log {

  scroll-snap-type-y: proximity 100px;

  scroll-snap-points-y: block-end;

}


It makes sense to avoid a brand new set of css attributes to provide a way
of maintaining a scroll offset if we could re-use the existing scroll snap
ones. This also means that we don't have to worry about creating
potentially unexpected conflicts between snap-point and scroll-anchor
guarantees
(imagine a mandatory snap point that falls within range of a scroll-anchor!)
.

Best regards,
Majid


[1] "Whenever the size of the scrollable area changes, if an element is
scroll-anchored
<https://tabatkins.github.io/specs/css-sticky-scrollbars/#scroll-anchored> to
any scroll-anchor edges
<https://tabatkins.github.io/specs/css-sticky-scrollbars/#scroll-anchor-edges>,
it must adjust its scroll position to maintain the same distance from that
edge as it had before the scrollable area changed size."

[2] "If the content changes such that the visual viewport would no longer
rest on a snap point (e.g. content is added, moved, deleted, resized), the
scroll offset must be modified to maintain this guarantee."

Received on Tuesday, 30 June 2015 14:23:28 UTC