tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

scrollIntoView-fixed.html (8988B)


      1 <!DOCTYPE html>
      2 <html>
      3  <head>
      4    <title>CSSOM View - scrollIntoView from position:fixed</title>
      5    <meta charset="utf-8">
      6    <meta name="viewport" content="width=device-width,minimum-scale=1">
      7    <link rel="author" title="David Bokan" href="mailto:bokan@chromium.org">
      8    <link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-element-scrollintoview">
      9    <script src="/resources/testharness.js"></script>
     10    <script src="/resources/testharnessreport.js"></script>
     11    <style>
     12      body {
     13        width: 1000vw;
     14        height: 1000vh;
     15        /* stripes so we can see scroll offset more easily */
     16        background: repeating-linear-gradient(
     17          45deg,
     18          #A2CFD9,
     19          #A2CFD9 100px,
     20          #C3F3FF 100px,
     21          #C3F3FF 200px
     22        );
     23      }
     24 
     25      .fixedContainer {
     26        position: fixed;
     27        bottom: 10px;
     28        left: 10px;
     29        width:  150px;
     30        height: 150px;
     31        background-color: coral;
     32      }
     33 
     34      .fixedContainer.scrollable {
     35        overflow: auto;
     36        left: unset;
     37        right: 10px;
     38      }
     39 
     40      button {
     41        position: absolute;
     42        margin: 5px;
     43      }
     44 
     45      .target {
     46        position: absolute;
     47        width: 10px;
     48        height: 10px;
     49        background-color: blue;
     50        left: 50%;
     51        top: 50%;
     52      }
     53 
     54      .scrollable .target {
     55        left: 200%;
     56        top: 200%;
     57      }
     58 
     59      iframe {
     60        width: 96vw;
     61        height: 300px;
     62        position: absolute;
     63        left: 2vw;
     64        top: 100px;
     65      }
     66    </style>
     67    <script>
     68    </script>
     69  </head>
     70  <body>
     71    <div style="width:90vw">
     72      <p>
     73        The orange boxes are position: fixed. Clicking ScrollIntoView in each box
     74        will attempt to scroll into view the blue target element inside that fixed
     75        container to block/inline: start (i.e. aligned with top left corner in RTL).
     76      </p>
     77      <p>
     78        scrollIntoView from a position:fixed element must not scroll its
     79        containing frame; however, it must scroll further ancestor scrollers as
     80        the element isn't fixed in relation to them.
     81      </p>
     82    </div>
     83    <iframe></iframe>
     84    <div class="fixedContainer">
     85      Box A
     86      <button id="fixedContainerBtn">ScrollIntoView</button>
     87      <div class="target"></div>
     88    </div>
     89    <div class="fixedContainer scrollable">
     90      Box C
     91      <button id="scrollableFixedContainerBtn">ScrollIntoView</button>
     92      <div class="target"></div>
     93    </div>
     94    <script>
     95      if (typeof setup != 'undefined') {
     96        setup({ explicit_done: true });
     97        window.addEventListener("load", runTests);
     98      }
     99 
    100      function scrollIntoView(evt) {
    101        const container = evt.target.closest('.fixedContainer');
    102        const target = container.querySelector('.target');
    103        target.scrollIntoView({block: 'start', inline: 'start'});
    104      }
    105 
    106      document.querySelectorAll('button').forEach((btn) => {
    107        btn.addEventListener('click', scrollIntoView);
    108      });
    109 
    110      const iframe = document.querySelector('iframe');
    111      iframe.onload = () => {
    112        frames[0].document.querySelectorAll('button').forEach((btn) => {
    113          btn.addEventListener('click', scrollIntoView);
    114        });
    115      }
    116      iframe.srcdoc = `
    117        <!DOCTYPE html>
    118        <style>
    119          body {
    120            height: 200vh;
    121            width: 200vw;
    122            /* stripes so we can see scroll offset more easily */
    123            background: repeating-linear-gradient(
    124              45deg,
    125              #C3A2D9,
    126              #C3A2D9 50px,
    127              #E5C0FF 50px,
    128              #E5C0FF 100px
    129            );
    130          }
    131          .fixedContainer {
    132            position: fixed;
    133            bottom: 10px;
    134            left: 10px;
    135            width:  150px;
    136            height: 150px;
    137            background-color: coral;
    138          }
    139 
    140          .fixedContainer.scrollable {
    141            overflow: auto;
    142            left: unset;
    143            right: 10px;
    144          }
    145 
    146          button {
    147            position: absolute;
    148            margin: 5px;
    149          }
    150 
    151          .target {
    152            position: absolute;
    153            width: 10px;
    154            height: 10px;
    155            background-color: blue;
    156            left: 50%;
    157            top: 50%;
    158          }
    159 
    160          .scrollable .target {
    161            left: 200%;
    162            top: 200%;
    163          }
    164        </style>
    165        IFRAME
    166        <div class="fixedContainer">
    167          Box B
    168          <button id="fixedContainerBtn">ScrollIntoView</button>
    169          <div class="target"></div>
    170        </div>
    171        <div class="fixedContainer scrollable">
    172          Box D
    173          <button id="scrollableFixedContainerBtn">ScrollIntoView</button>
    174          <div class="target"></div>
    175        </div>
    176      `;
    177 
    178      function reset() {
    179        [document, frames[0].document].forEach((doc) => {
    180          doc.scrollingElement.scrollLeft = 0;
    181          doc.scrollingElement.scrollTop = 0;
    182          doc.querySelectorAll('.fixedContainer').forEach((e) => {
    183            e.scrollLeft = 0;
    184            e.scrollTop = 0;
    185          });
    186        });
    187      }
    188 
    189      function runTests() {
    190        // Test scrollIntoView from a plain, unscrollable position:fixed element.
    191        // Nothing should scroll.
    192        test(() => {
    193          reset()
    194          const container = document.querySelector('.fixedContainer:not(.scrollable)');
    195          const target = container.querySelector('.target');
    196          target.scrollIntoView({block: 'start', inline: 'start'});
    197          assert_equals(window.scrollX, 0, 'must not scroll window [scrollX]');
    198          assert_equals(window.scrollY, 0, 'must not scroll window [scrollY]');
    199        }, `[Box A] scrollIntoView from unscrollable position:fixed`);
    200 
    201        // Same as above but from inside an iframe. Since the container is fixed
    202        // only to the iframe, we should scroll the outer window.
    203        test(() => {
    204          reset()
    205          const container = frames[0].document.querySelector('.fixedContainer:not(.scrollable)');
    206          const target = container.querySelector('.target');
    207          target.scrollIntoView({block: 'start', inline: 'start'});
    208 
    209          // Large approx to account for differences like scrollbars
    210          assert_approx_equals(window.scrollX, 100, 20, 'must scroll outer window [scrollX]');
    211          assert_approx_equals(window.scrollY, 300, 20, 'must scroll outer window [scrollY]');
    212          assert_equals(frames[0].window.scrollX, 0, 'must not scroll iframe [scrollX]');
    213          assert_equals(frames[0].window.scrollY, 0, 'must not scroll iframe [scrollY]');
    214        }, `[Box B] scrollIntoView from unscrollable position:fixed in iframe`);
    215 
    216        // Test scrollIntoView from a scroller that's position fixed. The
    217        // scroller should be scrolled but shouldn't bubble the scroll as the
    218        // window scrolling won't change the target's position.
    219        test(() => {
    220          reset()
    221          const container = document.querySelector('.fixedContainer.scrollable');
    222          const target = container.querySelector('.target');
    223          target.scrollIntoView({block: 'start', inline: 'start'});
    224          // Large approx to account for differences like scrollbars
    225          assert_equals(window.scrollX, 0, 'must not scroll window [scrollX]');
    226          assert_equals(window.scrollY, 0, 'must not scroll window [scrollY]');
    227          assert_approx_equals(container.scrollLeft, 145, 20,
    228              'scrollIntoView in container [scrollLeft]');
    229          assert_approx_equals(container.scrollTop, 145, 20,
    230              'scrollIntoView in container [scrollTop]');
    231        }, `[Box C] scrollIntoView from scrollable position:fixed`);
    232 
    233        // Same as above but from inside an iframe. In this case, the scroller
    234        // should bubble the scroll but skip its own frame (as it's fixed with
    235        // respect to its own frame's scroll offset) and bubble to the outer
    236        // window.
    237        test(() => {
    238          reset()
    239          const container = frames[0].document.querySelector('.fixedContainer.scrollable');
    240          const target = container.querySelector('.target');
    241          target.scrollIntoView({block: 'start', inline: 'start'});
    242          // Large approx to account for differences like scrollbars
    243          assert_approx_equals(window.scrollX, 740, 20, 'must scroll outer window [scrollX]');
    244          assert_approx_equals(window.scrollY, 360, 20, 'must scroll outer window [scrollY]');
    245          assert_approx_equals(container.scrollLeft, 145, 20,
    246              'scrollIntoView in container [scrollLeft]');
    247          assert_approx_equals(container.scrollTop, 145, 20,
    248              'scrollIntoView in container [scrollTop]');
    249          assert_equals(frames[0].window.scrollX, 0, 'must not scroll iframe [scrollX]');
    250          assert_equals(frames[0].window.scrollY, 0, 'must not scroll iframe [scrollY]');
    251        }, `[Box D] scrollIntoView from scrollable position:fixed in iframe`);
    252 
    253        done();
    254      }
    255 
    256    </script>
    257  </body>
    258 </html>