-
Notifications
You must be signed in to change notification settings - Fork 673
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[css-overflow] Proposing scroll-start
: allowing overflow scroll to not always start at 0 on 1st layout pass
#6986
Comments
+1 this would make scroll up for search or scroll up for nav really easy. These are common patterns in some native apps, for example iOS uses scroll up for search in numerous places. |
Hey 👋 In addition to Would be great to have keyword values like those used with the Flexbox API ✨ scroll-start: < center | auto | end | start | explicit value >; ʕ´•ᴥ•`ʔ |
center, start and end added to the explainer! great suggestions thanks! |
If this is a < length > value I assume percentages would work and you might not need keywords. Although you could always have both. I also assume if you set it to a value like 50vh this would scroll down to half the height of the viewport on initial render but not be relative going forward? Similar with percentage values? Or do they remain relative until the scroll is interacted with thus changing the scroll position? |
they're already specced as
they're active until interacted with yep, at which point they not longer apply. from the explainer "Once the user has interacted with the scroll area, scroll-start and scroll-start-target has no effect. The styles must be present during scrollport creation or they have otherwise missed their timing." |
For people who use the keyboard to navigate : would this impact the starting position of the focus ? Otherwise the first time you press TAB you'll be taken back to the beginning of the scroll area. |
Excellent consideration. I imagine a developer using this new prop could/would have already been managing tab/focus management should pair closely with this prop. it'd be a good idea to mention that in the explainer/docs though thanks! 👍🏻 |
The idea itself is great! Thank you @argyleink for bringing that up! I have some notes, though.
To answer those questions here's my counter-proposal:
Examples (rewritten from the initial comment): :root { --nav-height: 100px; }
.snap-scroll-y {
scroll-position: 0 var(--nav-height);
} .snap-scroll-inline {
overflow-inline: scroll;
scroll-snap-type: inline mandatory;
scroll-position: selector(#snap-start);
} Explanation: We concentrate the functionality in one property set on the scroll container. As this initial scroll position only has effect on scrollport creation before any user interaction, it means the DOM already needs to be fully available at that point in time. So setting it on the container with a selector for the child should be fine. Additional note: The property is independent from the things defined in CSS Scroll Snap 1. I.e. you can define a scroll position without having any scroll snap containers. Having said all that, another approach could be to align with CSS Scroll Snap 1, and there specifically with Sebastian |
i suppose this could get discussed more, but i do still feel like
Explainer says it's the 1st in the DOM order with the property. So competition is resolved by 1st node found. Matches your proposal too it looks like.
Like scroll-snap, some of the style is specified by the scrollview and some by a child. The original explainer used Thanks for the thoughts! Hopefully my answers seem reasonable 🙂 |
The tradeoff using
I don't see that in the explainer, though if it's meant to match my proposal, it's fine for me. 😄
My point was that it's not strictly necessary to have two properties for that because the use cases can be covered by a single one. Though I don't have a strong opposition against adding two.
Just for the record, My first point still stands, though. The names should be chosen so that it's clear that they don't have a shorthand-longhand relation. Sebastian |
Using a selector() is a last-resort kind of thing, when there's no way to scope the element you're associating with. Requiring an ID is onerous, and still doesn't actually give you uniqueness; allowing more general selectors gives you the same non-uniqueness issues you're trying to avoid. Here, it's straightforward - you want a descendant of the scroll container. Having the target self-select is a pretty straightforward and normal way to handle this. When there's more than one element advertising itself as the target, you just take the first in tree order or something. |
Related problem: baseline alignment to arbitrary child #1339 |
I think this is also related to #6225, which is about integration with history and navigations. |
Two issues that the explainer should address:
|
Also need to spec how this interacts with scroll anchoring: https://drafts.csswg.org/css-scroll-anchoring/ |
The CSS Working Group just discussed
The full IRC log of that discussion<dael> Topic: [css-overflow] Proposing scroll-start: allowing overflow scroll to not always start at 0 on 1st layout pass<dael> github: https://github.com//issues/6986 <dael> argyle: Goal, we did survey asking devs about experience in scroll. Starting to write explainers <dael> argyle: Scroll-start has overlap with frag navigation conceptually. But that is more magical b/c has more work to do and integrations to things like page refresh <smfr> q+ <dael> argyle: This wants to bring a portion of that power to move someone. Example is tabs to swipe between and want tos tart on a midway tab so it laysout at that tab <dael> argyle: All solutions to do this now take extra time and additional work <dael> argyle: Tucking a search bar above the fold is common. Spotify does this where you don't see search until you scroll up <dael> argyle: Proposal is advocating for way to do that in css using links as default. scroll-start 20px from top. Could also use % <dael> argyle: This would only apply if frag nav isn't used and user hasn't interacted with scroll. Waiting for checks listed in explainer to make sure it's untouched <dael> argyle: If so on first layout layout at this position <dael> argyle: Adds scroll-start:target which is where you can have a child as a target for scroll. Akin to scroll-snap where you can snap on first layout. But after that you can't scroll anywhere <dael> argyle: People hack around this by setting a keyframe. Have a snap child, wait a keyframe, and then remove an animation to remove the snap so you can move <dael> argyle: Offering something simple for this <dael> argyle: Property on the child where child in scroll container says snap to me if user hasn't ineracted with page <Rossen_> q? <dael> argyle: Additional details int he proposal, but how is that for a first pass? <dael> smfr: I like proposal. Useful functionality. Like that it's element-based target <dael> smfr: question is if we can define first layout pass. If page toggles display none and then goes back does that trigger first layout? If the layout tree is distroyed is that first layout? <dael> argyle: Nice. I hadn't articulated the proper timing. Makes sense as a request for the explainer. Thank you <Rossen_> ack smfr <Rossen_> ack fantasai <dael> fantasai: I think the idea of doing this makes a lot of sense. <dael> fantasai: Being able to choose and element and have it be focus makes sense <heycam> q+ <dael> fantasai: Agree with TabAtkins should be property on element not scroll container <dael> fantasai: Have a similar problem with baseline alignment and alining to child. 1339 issue <dael> fantasai: Should make them consistent in how they lookup <dael> fantasai: Makes sense overall and I support working on it <flackr> q+ <dael> argyle: So in favor of child property but don't agree with scroll port property of scroll-start? <dael> fantasai: NOt sure if we need opt in for scroller, but scroller shouldn't pick position <dael> argyle: Absolutely <dael> fantasai: In terms of figuring out how element aligns in port we should reuse snap. I think alignment question is handled by scrollsnap. You do h ave question of first or last element that qualifies <dael> fantasai: Another interaction, content alignment can effect initial scroll position. Have to figure out how that interacts <dael> argyle: Thank you. Taken notes <dael> argyle: In explainer does say if parent and child both have or multiple children have snap target it has how to resolve. Currenlty first in dom <dael> fantasai: Good answer. First in dom makes a lot of sense. Want to think about if an element can block it's children from participating in that <dael> argyle: Thank you <Rossen_> ack heycam <dael> heycam: Wondering what should happen when the page is loading slowly or content is added to scroll container and first layout happens before target offset is reached. Keep reevaluating to determine if we do a scroll until condition is met? <dbaron> Not just lazy addition from script, but also a large page that does the first layout of the container when only some of its content has been loaded. <dael> argyle: Current mentality is this is easy to interrupt. It's a request. In case of something being lazy I would assume...say it's scroll-start:left 200px. If it did first layout and nothing has happened I would say if a scroll-start shows up later it's ignored. Scroll position is set <dael> heycam: A little worried authors would test on fast connection, get desired behavior, and then publish and scroll position isn't updated so looks weird <Rossen_> q <dael> fantasai: I think we should use logic for [missed] and this would be the feature for how that works <Rossen_> ack fantasai <Zakim> fantasai, you wanted to reply to that <dbaron> The logic for scrolling to targeted elements isn't very good -- I really wanted to try to improve it about 15 years ago but never got around to it. :-/ <fantasai> s/[missed]/scrolling to :target/ <dael> TabAtkins: Going to say the same <chrishtr> q+ <dael> argyle: And point of this is prevent janka nd be there first. Misses it's mark if containing scroll port has been created and there's no children. <fantasai> s/feature for/feature defining/ <dael> argyle: I'm assuming Java is appending, but maybe even a really long document. I'm inclined to say trying to prevent jank and we want to do it all before a user sees it <dael> iank_: It's possible that your html can slowly trickle in. I think that's heycam slow connection <Rossen_> ack flackr <dael> flackr: I wanted to reply to smfr and heycam points. In my mind see this as substitute for assumed 0 defaults scroll. So should reapply any time we would start at position 0. Probably not same as fragmenetion because that waits <dael> flackr: For css any time something introduced with scroll it shouldn't jump <dael> flackr: When an element becomes a scroll container we should look for this and jump to that unless doing other frag navigation <Rossen_> q? <fantasai> s/fragmenetion/fragment navigation/ <TabAtkins> +1 to flackr's points <Rossen_> ack dbaron <dael> dbaron: Related to flackr just said. My opinion is frag navigation is not very good. Had plan to fix around 2007 but kept postponing <dael> dbaron: Thing that happened 3 or 4 years ago that had some improvements. I would have liked to see frag nav try to scroll to frag more frequently and have astate to say if it should keep trying <dael> dbaron: Not what happened and might not be web compat <dael> dbaron: Maybe doing same as frag nav is okay, but I think it's not that great and could be better for users <Rossen_> ack chrishtr <fantasai> +1 to not specifying an offset; should choose an element, and align it based on properties in css-scroll-snap <dael> chrishtr: Had a thought similar to flackr and others. What if instead of spec some default offset you spec what scroll anchor target is at the beginning. And that remains until user does something. If page takes a while to load browser knows what target should be and as it loads browser centers it on screen <dael> argyle: Sounds interesting. Sound like overlap with scroll start target. Maybe target should behave as desc <dael> fantasai: I think if we go with idea that scroll-snap-target aligns the same as scroll snap properties. Scroll padding and margin and align can determine the position. I think that should handle the offsets. Not sure there's a use case for offset at start not being the same as if you were targetting to the element <iank_> What about for a large <canvas> within a scroller where you don't have an element to target? <dael> argyle: Hearing advocacy for scroll-start:target and no scroll-start b/c in general want to scroll an item into view <dael> argyle: There are people that wanted keywords or end and center that are 100% or 50% <Rossen_> q? <dael> argyle: See what you're saying that length would be less used. <TabAtkins> Agree we *sometimes* want an explicit offset. <dael> argyle: Does seem like ti should be an offering. Like i know by hearder is 50 px and what to be under that <smfr> maybe this should also cover the “always scrolled to the bottom“ case for chats etc <dael> fantasai: You want to target the thing under the heading so that you can change the font on your heading and have it still work <dael> fantasai: You can already to top of bottom with align content <dael> TabAtkins: There's a use case in chat where you can't do offset. Large canvas in a scroller <dael> fantasai: Can see that. Can also see if doing fancy with canvas you want to define snap areas. more to be done with canvas <chrishtr> Re large canvas: there should be a way to specify a position relative to that element <dael> argyle: Another is shopping where image takes up show screen. Start with that in center and then you can pan. <Rossen_> q? <dael> fantasai: I believe align content is defined to do that <fantasai> https://www.w3.org/TR/css-align-3/#overflow-scroll-position <dael> Rossen_: Seems like have positive consensus to adopt this proposal <dael> Rossen_: Sure there are details to work out <dael> Rossen_: I see smfr is adding some of those to the issue <dael> Rossen_: Assuming you're looking for resolution to adopt? <dael> argyle: Correct. Want way forward to prototype. Have demos and stuff for scrollsnap we're hoping to add scroll start <dael> fantasai: rec to draft this as level 2. it's going to work closely with properties to determine position <fantasai> s/level 2/scroll snap level 2/ <dael> Rossen_: Prop 1: Accept hte proposal for scroll-start and add to scroll snap L2 <dael> Rossen_: Objections? <dael> fantasai: No obj but would like to hold off on adding the offset and start with the element. Should look at use cases <dael> Rossen_: If we have this in its own draft much easier to tease out issues <dael> Rossen_: Didn't hear objections <dael> RESOLVED: Accept the proposal for scroll-start and add to scroll snap L2 <dael> Rossen_: Question 2, who will do this? Do we need to add argyle as an editor? <dael> TabAtkins: Good idea if he's okay <dael> argyle: Happy to join in <dael> Rossen_: Obj to add argyle as a co-editor of scroll snap l2 <dael> RESOLVED: Add argyle as a co-editor of scroll snap L2 <dael> argyle: Plenty more to come |
When there is multiple scroll-start-targets, can we let the author choose the selection mechanism? Say that we had a property called One use case is a scroll snap image gallery. If the container is narrow, you’d want to start at the snap position of the first image. But, if the scrollport have space enough, you’d want to start at the snap position of the second image so that more images are visible from the start. .snap-scroll-inline {
overflow-inline: scroll;
scroll-snap-type: inline mandatory;
scroll-start-target-selection: safe last;
}
.snap-scroll-inline > :nth-child(-n+2) {
scroll-start-target-inline: auto;
} |
cool use case, totally makes sense. to me though, sounds like container queries are the perfect way to handle this: .snap-scroll-inline {
overflow-inline: scroll;
scroll-snap-type: inline mandatory;
container-type: inline-size;
container-name: carousel;
}
@container carousel (width >= 720px) {
.snap-scroll-inline > :nth-child(-n+2) {
scroll-start-target-inline: auto;
}
} So mobile does no scroll start adjusting, aligns inline-start nicely with the rest of a column layout design. but if width goes above 720, then set the scroll start target as to "peek" and "hint" at the carousel breadth of content by setting the scroll start target to something other than the first item. thoughts on using container queries to manage a carousels available space and dynamic scroll start positioning? |
Container queries can definitively be used to handle this in many cases. However it requires that you know the approximate size and scroll snap alignment of the target elements, and possibly the scroll padding and margins as well. Say that you have a user editable gallery, where users can add images of any aspect-ratio. The images are sized so that that have the same area, so that a 16:9 and a 9:16 image are the same “size”. The only way to know if you can safely scroll to the second image is to calculate all the snap positions, and check them against the border-box of the first image to see if it is partly or fully scrolled out of the scroll container. I quite like how ‘overflow-position’ in css-align-3 works, and would love a similar approach here: Try to align the initial scroll with the last scroll-start-target, but only if it can be done without obscuring any previous elements. |
I agree with Sebastian that
I am a bit confused by CSS is not very consistent with default values in shorthands. Sometimes they resolve to a previous value ( The behavior of the first category feels more natural to me when specifying a logical shorthand value, ie. I am not sure All logical shorthands currently map to their physical longhands. Related: #1282 |
This was marked as UD, however, all of the features have been discussed. Previous resolutions: scroll-start: w3c#6986 (comment) :snapped, snapChanged and snapChanging and creation of css-scroll-snap-2 ED: w3c#6985 (comment)
This was marked as UD, however, all of the features have been discussed. Previous resolutions: scroll-start: #6986 (comment) :snapped, snapChanged and snapChanging and creation of css-scroll-snap-2 ED: #6985 (comment)
Just in case: today I wrote a post where I shared a workaround for this that uses scroll-snap — https://blog.kizu.dev/snappy-scroll-start/ That workaround is not very convenient, mostly due to the interop issues with the current scroll-snap (I'll investigate them at a later time), but if someone needs |
📄 Explainer
Currently, JavaScript needs to show up at "never the right time" to adjust a scroll position to a specific starting place. This CSS property proposal seeks to remedy page load scroll jank by allow specifying a
scroll-start
position with a specific or by giving a child elementscroll-start-target: auto
at which point an absolute length is derived from the element and the scroll direction.Example: set the start position to an absolute value:
Example: set the start position to a snap child
There's a lot more use cases and details (like interaction with fragment navigation) about the proposal in the Explainer
Would love to present the details of the explainer to the CSSWG for feedback 🙂
The text was updated successfully, but these errors were encountered: