-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
I2I: amp-fx=float-in-(top|bottom) #20881
Comments
I have a use case for #20125, which has been closed in favor of this issue. For context, it's what I outlined here: #21016 (comment) I can partially implement this with position observer, amp-animation, Is |
I feel strongly that we shouldn't expose |
Partial for #20881. Base implementation for `amp-fx="float-in-(top|bottom)"`. Slides elements in-and-out accordingly. Matches behavior of Google viewer's sliding header, see http://go/amp-viewer-scroll and http://go/amp-viewer-scroll-thresholds internally. Demo: https://scroll-toggle.glitch.me/ Also: * refactors `amp-fx-collection` for types and size. (~10% down from total bundle) * adds a bunch of string → types tests (and killed a splice bug, thanks @amphtml-lgtm-bot!)
Partial for ampproject#20881. Base implementation for `amp-fx="float-in-(top|bottom)"`. Slides elements in-and-out accordingly. Matches behavior of Google viewer's sliding header, see http://go/amp-viewer-scroll and http://go/amp-viewer-scroll-thresholds internally. Demo: https://scroll-toggle.glitch.me/ Also: * refactors `amp-fx-collection` for types and size. (~10% down from total bundle) * adds a bunch of string → types tests (and killed a splice bug, thanks @amphtml-lgtm-bot!)
Partial for ampproject#20881. Base implementation for `amp-fx="float-in-(top|bottom)"`. Slides elements in-and-out accordingly. Matches behavior of Google viewer's sliding header, see http://go/amp-viewer-scroll and http://go/amp-viewer-scroll-thresholds internally. Demo: https://scroll-toggle.glitch.me/ Also: * refactors `amp-fx-collection` for types and size. (~10% down from total bundle) * adds a bunch of string → types tests (and killed a splice bug, thanks @amphtml-lgtm-bot!)
Implemented! |
Background
#20125 requests a feature to track scrolling in order to hide/show headers:
This approach more or less works, but it has some drawbacks and open questions that the alternative described here would eliminate.
Goal
To provide an independent component for element toggling on scroll for performance, UX and DX.
Issues with event-trigger approach
amp-animation
usage and definitionThe main use-case for this feature is presumably toggled headers on scroll up/down, similar to behavior on the Google SERP viewer, Safari/Chrome for iOS or Chrome for Android. In order to build such a feature using the method described in #20125, the author would need to define three separate things: action handlers for
scrollUp
/scrollDown
, anamp-animation
for scrollDown and anamp-animation
for scrollUp.Not only is this tedious but it's also fragile. In order to create an e.g. a slide-to-toggle-header animation, the absolute value of the translate has to match the the header's height and be included twice; once for each animation. This can obviously lead to mismatching and would be better off being calculated dynamically, similar to how
amp-story
handles animation presets.Responsive designs are also an issue in this case, since headers could vary by height, so multiple elements and animations would have to be included for each media query configuration, aided by a combination of transparency and
pointer-events: none
CSS nightmare.The
amp-animation
requirement is also a performance issue, since the extension is rather large (currently at33.627kB
gzipped) and we could just simply evade it and perform simple CSS animations instead.Leaky abstraction
Triggering simple events on scroll may lead authors to hand-roll behavior where better performing alternatives are available, e.g.
amp-position-observer
, even if they're low-trust. Examples are scroll-bound or scroll-triggered animations, where listening to an element's position is a better pattern than listening to scroll events directly.UX
In a significant number of cases, AMPHTML pages are rendered in the Google SERP viewer, which has the same header-toggle-on-scroll behavior. The logic for deciding when to toggle is not strictly simple (internal: go/amp-viewer-scroll), and is bound to hard-coded thresholds (internal: go/amp-viewer-scroll-thresholds). If the AMP-side logic or thresholds do not match the viewer's, independent headers would be toggled at different times, which would be extremely awkward. If we get rid of the threshold configuration from the event-based approach this is not strictly an issue, but we would be exposing a misnamed/misleading API instead.
Semantics & Encapsulation
Similar to misnamed APIs, we have to consider where to put this.
Core. Bloat on render blocking script and attaching scroll handlers when we don't need to.
amp-position-observer
. It's an extension, so that's good. However the toggle-on-scroll feature doesn't quite fit with its model:PositionObserver
either uses available browser APIs or polyfills that are element-bound, not offset-bound. This feature would be completely parallel to the rest of the component, so it's a lose-lose: people who only want position observing will get scroll triggers regardless, and people who only want scroll triggers will get position observing too.amp-fx-collection
. Makes more sense with the use and is more likely to be included thanamp-position-observer
by itself.amp-fx-collection
Including a new fx preset allows us to encapsulate the desired behavior with clear boundaries and without bloat. It also enables some invariants that are good for UX and DX:
No overloading. Scroll handlers will be attached for this feature only, without exposing the events themselves. This ensures that authors don't hand-roll poor-performing and/or undesired behavior (like scroll-triggered scene animations or, god forbid, interstitials).
Sized & positioned. Headers will always be at the top. Bottom navigation will always be at the bottom. Toggled elements are restricted to a certain height relative to viewport so they don't hijack the document. Animation offsets are dynamically calculated, so everything is always translated and positioned correctly, regardless of media queries and without hard-coded offset literals.
High-level usage
The
amp-fx
attribute is set with eitherfloat-in-top
orfloat-in-bottom
.On build time,
amp-fx-collection
async'ly ensures that target:is no taller than a certain viewport percentageOtherwise, it will do nothing.
Triggering
The component attaches scroll handlers that match the Google SERP viewer's header-toggling logic, and thresholds for consistency. On toggle, it calculates animation offsets corresponding to the target element's height and triggers a time-bound animation.
Performance
Multiple
amp-fx="float-in-*"
elements can live in one page for different targets. A singleObservable
should be instantiated from a single scroll handle that all the elements will listen to.Opportunities
In Google SERP cases, we already receive a
postMessage
that tells us to toggle, including duration and curve. No additional scroll handlers would be needed and toggling logic would always match, regardless of viewer changes.Milestones
Drawbacks
It's up to the authors not to do this:
We can consider restricting the amount of toggle elements that are alive at once. Alas we don't currently do anything more sophisticated to disregard excessive floating elements, so relying on good faith that including several floating bars is bad UX would simply preserve the status quo.
/cc @ampproject/wg-ui-and-a11y @aghassemi @nainar @CrystalOnScript
The text was updated successfully, but these errors were encountered: