Skip to content
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-5][css-scroll-snap-2] Snapping and generating scroll-marker pseudo-elements from fragments #10715

Open
flackr opened this issue Aug 8, 2024 · 7 comments

Comments

@flackr
Copy link
Contributor

flackr commented Aug 8, 2024

For common carousel patterns as outlined in #9745, developers will have content being fragmented into different boxes. Often, developers want to create an interface that scrolls through these fragments by pages, e.g. demo. Similarly, for existing column fragmentation use cases developers may wish to snap to particular columns. Issues #6017 and #5911 both have prior discussion on snapping specifically.

As with snapping, it would be very convenient to be able to generate a ::scroll-marker pseudo-element per generated fragment to set up automatic markers based on the available space and number of resulting fragments the content ended up needing.

This explores the two issues together as they feel similar in nature, though we don't necessarily have to resolve on the same solution for both.

For the examples below, we have the following common styles:

.scroller {
  overflow: auto;
  height: 80vh;
  scroll-snap-type: x mandatory;
  columns: 1; /* Fragment content to horizontally scrollable full pages */
}

Options:

  1. Support scroll-snap-align (as suggested in [css-multicol-2][css-scroll-snap] Snapping to column boxes #6017) and ::scroll-marker pseudo-elements on a ::fragment selector1. This would allow a paginated carousel-like snapping experience to be created as follows:
    <style>
      .scroller::fragment {
        scroll-snap-align: center;
        &::scroll-marker {
          content: ' ';
        }
      }
    </style>
    <div class="scroller">
      <!-- flowing content or items, e.g. -->
      <div>Item 1</div>
      <div>Item 2</div>
      ...
      <div>Item n</div>
    </div>
  2. Make scroll-snap-align (as suggested in [css-scroll-snap] Scroll snap areas for fragmented boxes (like in css-multicol) #5911) and ::scroll-marker fragment aware. As per @tabatkins comment in the linked issue this seems to be the way that firefox behaves for scroll-snap-align already. If we go this way we may decide whether that ::scroll-marker should behave the same as well or that it should have a different solution. For our common example, this would require the use of a wrapping element to establish the fragment snap areas and markers:
    <style>
      .scroller > div {
        scroll-snap-align: center;
        &::scroll-marker {
          content: ' ';
        }
      }
    </style>
    <div class="scroller">
      <div> <!-- wrapping container generating snap areas and markers -->
        <!-- flowing content or items, e.g. -->
        <div>Item 1</div>
        <div>Item 2</div>
        ...
        <div>Item n</div>
      </div>
    </div>
  3. Introduce fragmentation aware values for these selectors / properties. This would provide a bit more capability as authors could specify for each sytled element which one should have its fragmented parts should generate a snap areas and/or scroll markers. Similar to option 2, this would also require wrapping the content for our common example case:
    <style>
      .scroller > div {
        scroll-snap-align: center per-fragment;
        &::scroll-marker(per-fragment) {
          content: ' ';
        }
      }
    </style>
    <div class="scroller">
      <div> <!-- wrapping container generating snap areas and markers -->
        <!-- flowing content or items, e.g. -->
        <div>Item 1</div>
        <div>Item 2</div>
        ...
        <div>Item n</div>
      </div>
    </div>
  4. Support scroll-snap-align (as suggested in [css-multicol-2][css-scroll-snap] Snapping to column boxes #6017) and ::scroll-marker pseudo-elements on a ::column selector. This would allow a paginated carousel-like snapping experience to be created as follows:
    <style>
      .scroller::column {
        scroll-snap-align: center;
        &::scroll-marker {
          content: ' ';
        }
      }
    </style>
    <div class="scroller">
      <!-- flowing content or items, e.g. -->
      <div>Item 1</div>
      <div>Item 2</div>
      ...
      <div>Item n</div>
    </div>
    This is similar to option 1, however is more clear about what is being styled. I think developers could think about this as decorating the columns, and the properties may not need to be inherited to the elements in the columns.

Footnotes

  1. Note that the current spec uses ::nth-fragment, however having a single element inherit different styles per fragment introduces significant implementation complexity. As such, we would propose initially resolving to go with a single ::fragment style (i.e. the syntax mentioned in the inline issue)

@flackr
Copy link
Contributor Author

flackr commented Aug 8, 2024

For option 1, there is an added complication that we don't have any way for @supports to detect which properties would be currently supported by the ::fragment selector. E.g. currently you can check for the existence of a property @supports scroll-snap-align: center) or a selector @supports selector(::fragment) but you wouldn't be able to check whether ::fragment supports any other properties, like color.

This seems to be a bit of a pre-existing issue with other pseudoclasses having a restricted set of supported properties that we may want to expand upon in the future, but I thought it was worth noting, e.g.

@lilles
Copy link
Member

lilles commented Aug 9, 2024

  1. Note that the current spec uses ::nth-fragment, however having a single element inherit different styles per fragment introduces significant implementation complexity. As such, we would propose initially resolving to go with a single ::fragment style (i.e. the syntax mentioned in the inline issue)

That would be pretty similar to ::first-line, yes.

For the single ::fragment case, would you then do inheritance from ::fragment into the elements laid out into fragments at style recalc time, reflected in getComputedStyle(), or keep a separate set of styles for layout like is done for ::first-line?

@flackr
Copy link
Contributor Author

flackr commented Aug 28, 2024

  1. Note that the current spec uses ::nth-fragment, however having a single element inherit different styles per fragment introduces significant implementation complexity. As such, we would propose initially resolving to go with a single ::fragment style (i.e. the syntax mentioned in the inline issue)

That would be pretty similar to ::first-line, yes.

I guess unlike ::first-line all content inherits from ::fragment since it is all in one of the fragments.

For the single ::fragment case, would you then do inheritance from ::fragment into the elements laid out into fragments at style recalc time, reflected in getComputedStyle(), or keep a separate set of styles for layout like is done for ::first-line?

I suspect we'd do inheritance from ::fragment into the elements at style recalc time, but I'm not sure I understand the differences and would welcome guidance here. @bfgeek had concerns with the original nth-fragment as an individual element would have one fragment inherit from one rule and a different one from a different rule, perhaps they can add more detail here?

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-overflow-5][css-scroll-snap-2] Snapping and generating scroll-marker pseudo-elements from fragments, and agreed to the following:

  • ACTION: fantasai to comment on the options
  • ACTION: rob to write up ::column option
The full IRC log of that discussion <bramus> flackr: one of the things that came up how devs can author content around auto paginated fragments (cols or page fragments int he future) is how do you actually attach scroll markers or snap styling?
<bramus> … or other things?
<bramus> … there is three general directions
<bramus> … the overflow spec already has mention of styling fragments
<bramus> … has an nth-fragment selector but there are internal concerns about it
<bramus> … one option to have a fragment selector that applies to all fragments
<bramus> … second option to make the indiv properities fragment aware
<bramus> … alreadu have issue for scroll-snap-align
<bramus> … (firefox and and chrome differ)
<bramus> … could decide that this is anice way to turn fragments int snap areas or markers
<bramus> … third option is a different syntax to make the property aware of fragments
<bramus> … (code in issue)
<bramus> … second option is nice and simple
<bramus> … at least for snap areas: snap areas per fragment box
<bramus> … can do same for scroll markers but feels weird
<bramus> … maybe can go for something different?
<bramus> … this is the way to go or should be pursue fragment styling?
<TabAtkins> I don't have a strong opinion on this, but I support the use-case.
<TabAtkins> Doing it via a non-numbered ::fragment, to avoid implying different styling on fragments, seems useful
<bramus> astearns: also support the use case like but dont have feedback on choosing
<bramus> … anyone with better opinion?
<astearns> ack fantasai
<bramus> fantasai: i think a generic ::fragment representing column in multicol is confusing
<bramus> … bc we have several different ideas about fragmentation and multicol as one type of thing that creates fragments in a container
<bramus> … i think ?? set scroll-snap-aling on column makes sens but should do that with pseudo element
<rachelandrew> +1 for scrollsnapping on columns, we have issues for that.
<bramus> … one of the discussions in overflow spec was to have nth-fragment pseudo element
<astearns> s/with pseudo/with column pseudo/
<bramus> … it represents instances of the block through wihch the content fragments
<bramus> … very different concept from multicol cols which are boxes
<bramus> … inside the ??
<astearns> (discussing the overflow: fragment proposal)
<bramus> … dont think scrollsnapalign should target column when you set it on multicol
<bramus> … should target the col that allows the snap property on ??
<bramus> flackr: that is not what is listed in the issue
<bramus> … for option 2 it is saying tha tif you set ssa on the in the multicol
<bramus> … then should it generate are snap area per generated box
<bramus> fantasai: dont have good answer to that
<bramus> flackr: to be clear: not to set ssa on the thing establishing the multicol
<bramus> … q is wheter setting those should have an effect per fragment
<bramus> … could be per property
<bramus> fantasai: yes, transforms and borders for example differ
<bramus> flackr: brought it up as one possible way
<bramus> … if you want to snap align, you can wrap everything in multicol and then have sssa
<bramus> fantasai: <missed>
<bramus> … on last col it would be kinda weird
<astearns> s/<missed>/it would be better to set scroll snapping on the columns themselves/
<bramus> … as content could be shorter than the others
<bramus> flackr: yes, so vertical cneter would align differently
<bramus> iank_: there are usecases for if you have a fragmented box somehwere within multicol to generate a snap area per fragment
<bramus> … so that would still be useful
<bramus> … option 2 if we agree that generating snap are per fragment is strictly better behavior (like firefox) … could resolve on that
<bramus> … other prior art is box-decoration-break
<bramus> … dont think that makes … could explore that route
<bramus> … producing snap area per ? might be better behavior
<bramus> flackr: would solve the snap proble,
<bramus> … also need to decide on scroll markers
<bramus> astearns: so proposal to resolve on option 2 for snap areas
<bramus> … which would be in line with how firefox behaves
<bramus> flackr: yes
<fantasai> I'm not sure, in a multicol it might make sense to use the bounding box as the stanp area
<bramus> astearns: any concerns with that? or more time needed?
<fantasai> s/stanp/snap/
<bramus> astearns: do you mean bounding box of all of the fragments, elika?
<fantasai> yes
<fantasai> if you imagine for example the use case of highlighting something
<bramus> astearns: (chair hat off) agree with ian that htere are use cases for snapping 2 fragments individually
<fantasai> and then snapping to that highlighted section
<bramus> … so elika i think you’d rather not resolve and take it back to issue?
<bramus> fantasai: yeah, not sure what to … e.g. article inside scroller and highlighting function to highlight things … would you expec tto snap to each one individually or the whole region? not sure
<iank_> q+
<bramus> … dont have objection to resolve on ??
<bramus> flackr: a thing I heard is that you would be happy with sth like option 1 if we had a selector based on columns instead of fragment?
<bramus> … is that correct?
<bramus> … would be happy to take that as a direction to pursue
<fantasai> I think we should solve the column-snapping problem directly
<bramus> iank_: dont think that solves all th euse cases like snap align
<fantasai> and for fragments within the columns, address them also directly
<bramus> flackr: agree, there is a separate issue for snap areas
<fantasai> not as a proxy for the column-snapping
<bramus> … could continue to pursue for fragmented snap area boxes
<bramus> … I think we can solve a lot of the use cases that i am tring to address with orig issue by having a ::column selector for example
<bramus> … to create some style for the area
<bramus> bramus: heard requests for grid on that
<bramus> … would that also work there, or only for fragmentation?
<bramus> iank_: no, probably not
<astearns> ack iank_
<bramus> … other thing:
<bramus> … if we agree that both cases are useful for ssa, then proposal 3 where we say scroll-snap-stop per fragment vs not
<bramus> … need to decided on default behavior for scroll marker ??
<bramus> … bc one thing here is tha tif we go with ::column that would initially only be valid on scroll marker group and ssa (?)
<bramus> astearns: so hearing all three options are sitll in play
<bramus> … let’s take back to issue
<bramus> … can you add comments to all options, fantasai?
<fantasai> ACTION: fantasai to comment on the options
<bramus> … bc there are some unanswered questions
<bramus> ACTION: rob to write up ::column option

@flackr
Copy link
Contributor Author

flackr commented Sep 4, 2024

ACTION: rob to write up ::column option

I've written up a fourth option (so as not to reorder the numbers) for this.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-overflow-5][css-scroll-snap-2] Snapping and generating scroll-marker pseudo-elements from fragments.

The full IRC log of that discussion <TabAtkins> flackr: Final thing that really helsp make this fall together is being able to use fragmentation to automatically create the "pages"
<TabAtkins> flackr: So if you specify that you have columns:1, that'll make one fragment per page
<TabAtkins> flackr: You could do multiple columns
<TabAtkins> flackr: we want to support some styling on these columns
<TabAtkins> flackr: scroll-snap-align is a notable one, to align the columns itself
<TabAtkins> flackr: not useful to stop a scroll halfway between columns, would rather it snap
<flackr> demo of columns: https://jsbin.com/modewaj/edit?html,output
<TabAtkins> flackr: the other use is generating a scroll marker
<TabAtkins> flackr: if a column is a destination you want to get to, you might want a scroll marker for it
<flackr> https://codepen.io/flackr/pen/yLmyPEV
<TabAtkins> flackr: combining these features, you can make this demo
<TabAtkins> flackr: note snap alingment isn't working yet
<TabAtkins> flackr: you can see the number of scroll-markers i generate changes as i chagne the container size, since different number of items fit on a scroll page
<TabAtkins> flackr: with snap-align support it would automatically snap to pages, arrows would work properly
<TabAtkins> flackr: this lets authors just write a list of content, and have it present in a full paginated experience
<flackr> TabAtkins: while this is fully generated, all of this can be done with real elements
<flackr> TabAtkins: allowing additional structure / semantics
<TabAtkins> syns: This really excited me, as someone who's lead a dev team thru a carousel
<TabAtkins> TabAtkins: our exploration revealed that there were basically *zero* correct carousels on the web
<wendyreid> q+
<TabAtkins> syns: but there are more correct ones ^_^

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-overflow-5][css-scroll-snap-2] Snapping and generating scroll-marker pseudo-elements from fragments, and agreed to the following:

  • RESOLVED: Add ::column pseudo, as a leaf node on the multicol, supporting scroll-marker and scroll-snap-align
The full IRC log of that discussion <TabAtkins> flackr: we had a previous discussion about the use-cases for snapping and generating scroll markers on column boxes
<TabAtkins> flackr: based on some of the discussion/concerns, i'm proposing we go with a fourth option
<TabAtkins> flackr: define a ::column pseudo
<TabAtkins> flackr: that you can attach scroll markers to, set scroll-snap-align on. potentially we could expose more props in the future
<TabAtkins> flackr: and I think this resolves a lot of the issues we had, and is consistent with some of elika's comments
<TabAtkins> +1 from me
<TabAtkins> Rossen4: Rune, you had comments on this issue
<TabAtkins> flackr: you commented on the ::nth-fragment option, but the proposal now is to go with a ::column pseudo
<TabAtkins> futhark: that's kinda a sidenote, about styling columns when elements fragment across them
<TabAtkins> futhark: is that relevant now?
<TabAtkins> flackr: I think there's one potentially relevant question here.
<TabAtkins> flackr: if you set scroll-snap-align:inherit...
<TabAtkins> futhark: yeah, which one do you align if an element breaks across columns
<TabAtkins> flackr: need to decide if we inherit
<TabAtkins> flackr: if we never support selecting particular columns, it's okay
<TabAtkins> flackr: but if we do, you could inherit different values on each fragment
<TabAtkins> fantasai: there shouldn't be inheritance
<TabAtkins> miriam: why?
<TabAtkins> fantasai: we could go either way in theory
<TabAtkins> fantasai: I think there are use-cases for having *some* sort of inheritable pseudo-element, but that's really complicated
<TabAtkins> fantasai: but a lot of times you just want to address the pseudo itself as a box
<TabAtkins> fantasai: another issue, ::column is a pretty generic name, we have columns elsewhere.
<miriam> got it, makes sense - thanks
<TabAtkins> fantasai: if we have it just be a leaf box in the tree, it's easier for us to reuse it in those other contexts
<TabAtkins> flackr: proposed resolution, add ::column pseudo-element as described in the issue
<TabAtkins> flackr: it's a leaf node (nothing inherits from it), and it supports scroll-marker and scroll-snap-align for now
<futhark> q+
<Rossen4> ack futhark
<TabAtkins> futhark: you said nothing inherits from it, what about ::scroll-marker?
<TabAtkins> fantasai: nothing *in the tree* inherits from it. chained pseudos still do, as normal
<TabAtkins> RESOLVED: Add ::column pseudo, as a leaf node on the multicol, supporting scroll-marker and scroll-snap-align

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Friday morning
Development

No branches or pull requests

6 participants
@flackr @lilles @astearns @chrishtr @css-meeting-bot and others