wpt / css / css-overflow / single-axis-scroll-apis-programmatic.html

Status: FAIL | Duration: 50ms | Subtests: 1/4 | Open test on wpt.live | wpt.fyi

Data from commit:
a50cb89 wpt: run reference-named files which are themselves tests (#836) (2026-09-03)

SubtestStatusMessage
LTR clipped XFAILassert_equals: LTR clipped X: scrollTo ignores the clipped X-axis expected 0 but got 40
RTL clipped XPASS
LTR clipped YFAILassert_equals: LTR clipped Y: scrollTo ignores the clipped Y-axis expected 0 but got 50
RTL clipped YFAILassert_equals: RTL clipped Y: scrollTo updates the unclipped X-axis (negative in RTL) expected -40 but got 0

/css/css-overflow/single-axis-scroll-apis-programmatic.html

<!doctype html>
<meta charset="utf-8">
<title>Single-axis scroll containers with programmatic scroll APIs</title>
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-element-scrollto">
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-element-scrollby">
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-element-scrollwidth">
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-element-scrollheight">
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/5572">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>

<style>
  .scroller {
    width: 100px;
    height: 100px;
    scrollbar-width: none;
  }
  .clip-x {
    overflow-x: clip;
    overflow-y: scroll;
  }
  .clip-y {
    overflow-x: scroll;
    overflow-y: clip;
  }
  .rtl {
    direction: rtl;
  }
  .content {
    width: 300px;
    height: 300px;
  }
</style>

<!-- LTR scroller with clipped X -->
<div class="scroller clip-x">
  <div class="content"></div>
</div>

<!-- RTL scroller with clipped X -->
<div class="scroller clip-x rtl">
  <div class="content"></div>
</div>

<!-- LTR scroller with clipped Y -->
<div class="scroller clip-y">
  <div class="content"></div>
</div>

<!-- RTL scroller with clipped Y -->
<div class="scroller clip-y rtl">
  <div class="content"></div>
</div>

<script>
function assertOverflowDimensions(scroller, label) {
  assert_equals(scroller.scrollWidth, 300,
      `${label}: scrollWidth retains overflowing content size`);
  assert_equals(scroller.scrollHeight, 300,
      `${label}: scrollHeight retains overflowing content size`);
}

test(() => {
  const scroller = document.querySelector('.scroller.clip-x');

  assert_equals(scroller.scrollLeft, 0,
      'LTR clipped X: scrollLeft is set to default value of 0');

  scroller.scrollTo(40, 50);
  assert_equals(scroller.scrollLeft, 0,
      'LTR clipped X: scrollTo ignores the clipped X-axis');
  assert_equals(scroller.scrollTop, 50,
      'LTR clipped X: scrollTo updates the unclipped Y-axis');

  scroller.scrollBy(20, 20);
  assert_equals(scroller.scrollLeft, 0,
      'LTR clipped X: scrollBy ignores the clipped X-axis');
  assert_equals(scroller.scrollTop, 70,
      'LTR clipped X: scrollBy incrementally updates the unclipped Y-axis (50 + 20 = 70)');

  scroller.scrollLeft = 70;
  assert_equals(scroller.scrollLeft, 0,
      'LTR clipped X: setting scrollLeft ignores the clipped X-axis');
  assert_equals(scroller.scrollTop, 70,
      'LTR clipped X: setting scrollLeft leaves the unclipped Y-axis unchanged');

  assertOverflowDimensions(scroller, 'LTR clipped X');
}, 'LTR clipped X');

test(() => {
  const scroller = document.querySelector('.scroller.clip-x.rtl');

  scroller.scrollTo(-40, 50);
  assert_equals(scroller.scrollLeft, 0,
      'RTL clipped X: scrollTo ignores the clipped X-axis (negative in RTL)');
  assert_equals(scroller.scrollTop, 50,
      'RTL clipped X: scrollTo updates the unclipped Y-axis');

  scroller.scrollBy(-20, 20);
  assert_equals(scroller.scrollLeft, 0,
      'RTL clipped X: scrollBy ignores the clipped X-axis');
  assert_equals(scroller.scrollTop, 70,
      'RTL clipped X: scrollBy incrementally updates the unclipped Y-axis (50 + 20 = 70)');

  scroller.scrollLeft = -70;
  assert_equals(scroller.scrollLeft, 0,
      'RTL clipped X: setting scrollLeft ignores the clipped X-axis');
  assert_equals(scroller.scrollTop, 70,
      'RTL clipped X: setting scrollLeft leaves the unclipped Y-axis unchanged');

  assertOverflowDimensions(scroller, 'RTL clipped X');
}, 'RTL clipped X');

test(() => {
  const scroller = document.querySelector('.scroller.clip-y');

  scroller.scrollTo(40, 50);
  assert_equals(scroller.scrollLeft, 40,
      'LTR clipped Y: scrollTo updates the unclipped X-axis');
  assert_equals(scroller.scrollTop, 0,
      'LTR clipped Y: scrollTo ignores the clipped Y-axis');

  scroller.scrollBy(20, 20);
  assert_equals(scroller.scrollLeft, 60,
      'LTR clipped Y: scrollBy incrementally updates the unclipped X-axis (40 + 20 = 60)');
  assert_equals(scroller.scrollTop, 0,
      'LTR clipped Y: scrollBy ignores the clipped Y-axis');

  scroller.scrollTop = 70;
  assert_equals(scroller.scrollLeft, 60,
      'LTR clipped Y: setting scrollTop leaves the unclipped X-axis unchanged');
  assert_equals(scroller.scrollTop, 0,
      'LTR clipped Y: setting scrollTop ignores the clipped Y-axis');

  assertOverflowDimensions(scroller, 'LTR clipped Y');
}, 'LTR clipped Y');

test(() => {
  const scroller = document.querySelector('.scroller.clip-y.rtl');

  scroller.scrollTo(-40, 50);
  assert_equals(scroller.scrollLeft, -40,
      'RTL clipped Y: scrollTo updates the unclipped X-axis (negative in RTL)');
  assert_equals(scroller.scrollTop, 0,
      'RTL clipped Y: scrollTo ignores the clipped Y-axis');

  scroller.scrollBy(-20, 20);
  assert_equals(scroller.scrollLeft, -60,
      'RTL clipped Y: scrollBy incrementally updates the unclipped X-axis (-40 + -20 = -60)');
  assert_equals(scroller.scrollTop, 0,
      'RTL clipped Y: scrollBy ignores the clipped Y-axis');

  scroller.scrollTop = 70;
  assert_equals(scroller.scrollLeft, -60,
      'RTL clipped Y: setting scrollTop leaves the unclipped X-axis unchanged');
  assert_equals(scroller.scrollTop, 0,
      'RTL clipped Y: setting scrollTop ignores the clipped Y-axis');

  assertOverflowDimensions(scroller, 'RTL clipped Y');
}, 'RTL clipped Y');
</script>