w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 667 forks source link

[css-conditional-5] Add `scroll-state(scroll-to)` container feature queries #11191

Open yisibl opened 2 days ago

yisibl commented 2 days ago

The overflowing(will be renamed to scrollable) feature in the current specification is confusing, and @fantasai expressed similar concerns in #11182.

This proposal attempts to explore solutions to more common scenarios.

CSS authors often prefer to get a sense of where the container has scrolled to, and then adapt behavior and style.

Proposal

Common use cases

  1. Display a back to top button after scrolling to the bottom of the page.
  2. In a horizontally scrolling table or carousel, when scrolling to the left or right, play a “rubber band” animation to indicate that the user has scrolled to the last page. See the demo below.👇🏻

Details

The current overflowing feature performs this once every time the page is loaded, which is undesirable in the above use case.

Demo

This is the syntax used in the demo video:

.table-box {
  overscroll-behavior-x: contain;
  overflow: auto;
}
@container scroll-state(overflowing: left) { /* or scrollable: left */
  table {
    animation: slide-right .5s linear;
  }
}

@container scroll-state(overflowing: right) { /* or scrollable: right */
  table {
    animation: slide-left .5s linear;
  }
}

Compare this to the following syntax, which implements the same functionality, but with better readability.

@container scroll-state(scroll-to: right) {
  table {
    animation: slide-right .5s linear;
  }
}
@container scroll-state(scroll-to: left) {
  table {
    animation: slide-left .5s linear;
  }
}

https://github.com/user-attachments/assets/f917d6b2-1e6f-42e7-9cbf-91b14f29bc9d

yisibl commented 2 days ago

Thinking further, is it possible to allow <length-percentage>? To do this, introduce the same scroll-x/y as background-position-x/y.

/* Scroll to 200px from the top to display the Back to Top button */
@container scroll-state(scroll-y >= 200px) {
  .back-to-top {
    display: block;
  }
}

This has functional overlap with Scroll-driven Animations, but I think it would be easier to use and more ergonomic.

fantasai commented 1 day ago

@yisibl At that point, I think you'll want to know the position of an element, not just an arbitrary length.