- From: Florian Rivoal <florian@rivoal.net>
- Date: Mon, 29 Jun 2015 23:05:35 +0200
- To: www-style list <www-style@w3.org>
- Cc: "Tab Atkins Jr." <jackalmage@gmail.com>
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
Received on Monday, 29 June 2015 21:06:06 UTC