AMP

amp-position-observer

Description

Monitors the position of an element within the viewport as a user scrolls, and dispatches events that can be used with other AMP components.

 

Required Scripts

<script async custom-element="amp-position-observer" src="https://cdn.ampproject.org/v0/amp-position-observer-0.1.js"></script>

Supported Layouts

Usage

The amp-position-observer component monitors the position of an element within the viewport as a user scrolls, and dispatches enter, exit and scroll:<Position In Viewport As a Percentage> events (Low Trust Level), which can be used to trigger actions (Only Low Trust Actions) on other components (e.g., amp-animation).

The amp-position-observer component is only useful when used with other components and does not do anything on its own.

Currently, amp-animation and several video players in AMP are the only components that allow low-trust events to trigger their actions (e.g., starting an animation, seeking to a position within the animation, pausing a video, etc.).

Scroll-bound animations

The amp-animation component exposes a seekTo action that can be tied to the scroll event of amp-position-observer to implement scroll-bound animations.

Example: Animation rotates as user scrolls

Imagine an animation where the hour hand of a clock rotates as the user scrolls the page.


<!-- An animation that rotates a clock hand 180 degrees. -->
<!--
   Note that we are NOT setting `trigger=visibility`
   since we will manually trigger the animation.
-->
<amp-animation id="clockAnim" layout="nodisplay">
  <script type="application/json">
    {
      "duration": "3s",
      "fill": "both",
      "direction": "alternate",
      "animations": [
        {
          "selector": "#clock-scene .clock-hand",
          "keyframes": [
            {"transform": "rotate(-180deg)"},
            {"transform": "rotate(0deg)"}
          ]
        }
      ]
    }
  </script>
</amp-animation>

<!-- The clock container -->
<div id="clock-scene">
  <!--
    Use amp-position-observer to tie the movement of the clock scene within
    the viewport to the timeline of the animation
  -->
  <amp-position-observer
    intersection-ratios="1"
    on="scroll:clockAnim.seekTo(percent=event.percent)"
    layout="nodisplay"
  >
  </amp-position-observer>
  <amp-img layout="responsive" width="2" height="1.5" src="./img/clock.jpg">
    <div class="clock-hand"></div>
  </amp-img>
</div>

Animation scenes that start/pause based on visibility in the viewport

The amp-animation component also exposes start and pause actions that can be tied to the enter and exit events of amp-position-observer to control when an animation starts/pauses based on visibility.

The amp-position-observer component exposes various visibility configurations such as intersection-ratios and viewport-margins (similar to IntersectionObserver) that can be used to fine-tune when the target is considered visible.

Example: Animation starts and pauses based on visibility

Consider the same clock animation, but this time the hand animates with time, except we like the animation to start when clock is at least 50% visible and pause as soon as clock becomes less than 50% visible.


<!-- An animation that rotates a clock hand 180 degrees. -->
<!--
   Note that we are NOT setting `trigger=visibility`
   since we will manually trigger the animation
-->
<!--
   Also note that this is the same animation as the scroll-bound version above
   the animation is the same, just the triggering mechanism with
   `amp-position-observer` is different!
-->
<amp-animation id="clockAnim" layout="nodisplay">
  <script type="application/json">
    {
      "duration": "3s",
      "fill": "both",
      "direction": "alternate",
      "animations": [
        {
          "selector": "#clock-scene .clock-hand",
          "keyframes": [
            {"transform": "rotate(-180deg)"},
            {"transform": "rotate(0deg)"}
          ]
        }
      ]
    }
  </script>
</amp-animation>

<!-- The clock container -->
<div id="clock-scene">
  <!--
    Use amp-position-observer to tie the start/pause of the animation with
    the visibility of the scene.
  -->
  <amp-position-observer
    intersection-ratios="0.5"
    on="enter:clockAnim.start;exit:clockAnim.pause"
    layout="nodisplay"
  >
  </amp-position-observer>

  <amp-img layout="responsive" width="2" height="1.5" src="./img/clock.jpg">
    <div class="clock-hand"></div>
  </amp-img>
</div>

Accessibility considerations for scroll-bound and visibility-based animations

Animations in general can present an issue for certain user groups. Scroll-bound and parallax animations in particular can be problematic for users with vestibular disorders. Make sure to review the advice provided in the accessibility considerations for amp-animation.

Attributes

target (optional)

Specifies the ID of the element to observe. If not specified, the parent< of <amp-position-observer> is used as the target.

intersection-ratios (optional)

Defines how much of the target should be visible in the viewport before <amp-position-observer> triggers any of its events. The value is a number between 0 and 1 (default is 0).

You can specify different ratios for top vs. bottom by providing two values (<top> <bottom>).

  • `intersection-ratios="0"` means `enter` is triggered as soon as a single pixel of the target comes into viewport and `exit` is triggered as soon as the very last pixel of the target goes out of the viewport.
  • `intersection-ratios="0.5"` means `enter` is triggered as soon as 50% of the target comes into viewport and `exit` is triggered as soon as less than 50% of the target is in the viewport.
  • `intersection-ratios="1"` means `enter` is triggered when target is fully visible and `exit` is triggered as soon as a single pixel goes out of the viewport.
  • `intersection-ratios="0 1"` makes the conditions different depending on whether the target is entering/exiting from top (0 will be used) or bottom (1 will be used).

viewport-margins (optional)

A px or vh value which can be used to shrink the area of the viewport used for visibility calculations. A number without a unit will be assumed px. Defaults to 0.

You can specify different values for top vs. bottom by providing two values (<top> <bottom>).

  • `viewport-margins="100px"` means shrink the viewport by 100px from the top and 100px from the bottom.
  • `viewport-margins="25vh"` means shrink the viewport by 25% from the top and 25% from the bottom. Effectively only considering the middle 50% of the viewport.
  • `viewport-margins="100px 10vh"` means shrink the viewport by 100px from the top and 10% from the bottom.

once (optional)

Only triggers the enter and exit events once. The scroll event will also only perform one iteration.

The presence of the attribute represents the true value and the absence of the attribute represents the false value. If the attribute is present, its value must be an empty string, once or not assigned.

Validation

See amp-position-observer rules in the AMP validator specification.

Potrzebujesz dodatkowej pomocy?

Znasz już ten dokument na wylot i nadal nie znajdujesz w nim odpowiedzi na wszystkie pytania? Być może inni przeszli to samo: skontaktuj się z nimi na Stack Overflow.

Przejdź do Stack Overflow
Udało Ci się trafić na błąd albo brakuje jakiejś funkcji?

Zdecydowanie zachęcamy do wzięcia udziału! Choć mamy nadzieję, że staniesz się stałym uczestnikiem naszej społeczności open source, to z wdzięcznością przyjmiemy również każdy jednorazowy wkład w kwestie, które są Twoją pasją.

Przejdź do GitHub