Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test has a WPT meta file that expects 4 subtest issues.
- This WPT test may be referenced by the following Test IDs:
- /css/css-overflow/parsing/getComputedStyle-scroll-button.html - WPT Dashboard Interop Dashboard
<!doctype html>
<meta charset="utf-8">
<title>CSS Overflow Test: getComputedStyle() resolves different properties for scroll-button pseudo-elements</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
.scroller {
width: 200px;
height: 200px;
overflow: auto;
}
#scroller-vertical {
writing-mode: vertical-rl;
direction: ltr;
}
/* Test 1: Horizontal LTR synonym matching */
#scroller-horizontal::scroll-button(inline-start) {
content: "A";
width: 30px;
height: 20px;
}
#scroller-horizontal::scroll-button(left) {
content: "B"; /* Should cascade and overwrite inline-start */
width: 35px;
height: 20px;
}
/* Test 2: Vertical-RL writing mode mapping */
#scroller-vertical::scroll-button(inline-start) {
content: "V-Start";
width: 45px;
height: 20px;
}
#scroller-vertical::scroll-button(up) {
content: "V-Up"; /* Should cascade and overwrite inline-start (which is up) */
width: 50px;
height: 20px;
}
#scroller-vertical::scroll-button(block-start) {
content: "V-BStart";
width: 55px;
height: 20px;
}
#scroller-vertical::scroll-button(right) {
content: "V-Right"; /* Should cascade and overwrite block-start (which is right) */
width: 60px;
height: 20px;
}
/* Test 3: Scroll button styled without 'content' (not generated) */
#scroller-no-content::scroll-button(inline-start) {
width: 80px;
height: 20px;
}
/* Test 4: Non-scroller originating element */
#not-scroller::scroll-button(inline-start) {
content: "<";
width: 90px;
height: 20px;
}
</style>
<div id="scroller-horizontal" class="scroller">
<div style="width: 500px; height: 100px;"></div>
</div>
<div id="scroller-vertical" class="scroller">
<div style="width: 500px; height: 500px;"></div>
</div>
<div id="scroller-no-content" class="scroller">
<div style="width: 500px; height: 100px;"></div>
</div>
<div id="not-scroller" style="width: 100px; height: 100px;"></div>
<script>
test(() => {
const scroller = document.getElementById("scroller-horizontal");
const styleStart = getComputedStyle(scroller, "::scroll-button(inline-start)");
const styleLeft = getComputedStyle(scroller, "::scroll-button(left)");
// In horizontal LTR, inline-start and left map to the same pseudo-element.
// Therefore, the 'left' rule (defined later) should cascade and overwrite
// the 'inline-start' rule, and both queries must return identical values.
assert_equals(styleStart.content, '"B"', "inline-start should return cascaded 'B'");
assert_equals(styleStart.width, "35px", "inline-start should return cascaded 35px");
assert_equals(styleLeft.content, '"B"', "left should return cascaded 'B'");
assert_equals(styleLeft.width, "35px", "left should return cascaded 35px");
}, "inline-start and left map to the same pseudo-element in horizontal LTR");
test(() => {
const scroller = document.getElementById("scroller-vertical");
// In vertical-rl LTR, inline-start is up (top).
// Therefore, 'up' (defined later) should overwrite 'inline-start'.
const styleStart = getComputedStyle(scroller, "::scroll-button(inline-start)");
const styleUp = getComputedStyle(scroller, "::scroll-button(up)");
assert_equals(styleStart.content, '"V-Up"', "inline-start should map to up and be overwritten");
assert_equals(styleStart.width, "50px", "inline-start width should be overwritten");
assert_equals(styleUp.content, '"V-Up"', "up should return 'V-Up'");
assert_equals(styleUp.width, "50px", "up width should be 50px");
// In vertical-rl LTR, block-start is right.
// Therefore, 'right' (defined later) should overwrite 'block-start'.
const styleBStart = getComputedStyle(scroller, "::scroll-button(block-start)");
const styleRight = getComputedStyle(scroller, "::scroll-button(right)");
assert_equals(styleBStart.content, '"V-Right"', "block-start should map to right and be overwritten");
assert_equals(styleBStart.width, "60px", "block-start width should be overwritten");
assert_equals(styleRight.content, '"V-Right"', "right should return 'V-Right'");
assert_equals(styleRight.width, "60px", "right width should be 60px");
}, "Writing-mode vertical-rl LTR correctly maps logical directions to physical directions");
test(() => {
const scroller = document.getElementById("scroller-no-content");
const styleStart = getComputedStyle(scroller, "::scroll-button(inline-start)");
// The pseudo-element is not created because it has no content.
// However, getComputedStyle() should still resolve and return the styled width.
assert_equals(styleStart.content, "normal", "Should return default 'normal' content");
assert_equals(styleStart.width, "80px", "Should correctly resolve styled width");
}, "getComputedStyle() resolves properties when pseudo-element is not created due to no content");
test(() => {
const notScroller = document.getElementById("not-scroller");
const styleStart = getComputedStyle(notScroller, "::scroll-button(inline-start)");
// The originating element is not a scroll container, so the pseudo-element
// is generated in a disabled state (since it has styled content).
// getComputedStyle() should resolve and return its styled properties correctly.
assert_equals(styleStart.content, '"<"', "Should correctly resolve styled content");
assert_equals(styleStart.width, "90px", "Should correctly resolve styled width");
}, "getComputedStyle() resolves properties when the originating element is not a scroll container");
test(() => {
const scroller = document.getElementById("scroller-horizontal");
const styleInvalid = getComputedStyle(scroller, "::scroll-button(invalid-argument)");
// Invalid argument should not crash the browser, and instead fall back cleanly.
assert_equals(styleInvalid.width, "", "Should fall back cleanly and return empty width");
}, "getComputedStyle() with invalid argument falls back cleanly and does not crash");
</script>