Summary
Suspected bug in Safari / WebKit: when an overlay using a CSS clip-path sits above a scrollable layer, wheel-scrolling in the clipped-out (invisible) region of the overlay passes through to the scroller beneath for "solid" clip-path shapes, but fails to pass through when the clip-path is a "frame" — i.e. the visible part is the outer border and the clipped-out part is an inner hole (a self-touching polygon subpath, default nonzero fill).
In the frame case, the inner hole is visually transparent, so per the hit-testing algorithm that determines wheel/pointer event targets it should be transparent to hit-testing as well — and wheel scroll there should reach the scroller beneath, just as it does for the clipped-out corners of a solid shape. In Safari it does not.
Repro shape (frame)
.cover {
width: 100%;
height: 100%;
position: absolute;
top: 0; left: 0;
background-color: blue;
opacity: 0.8;
clip-path: polygon(
0 0, 100% 0, 100% 100%, 0 100%, 0 25%,
25% 25%, 25% 75%, 75% 75%, 75% 25%, 0 25%
);
}
The user sees a semi-transparent blue frame around the content; the inner 50% is fully clear (clipped out). Wheel-scrolling inside that clear inner area does not reach the overflowing layer beneath in Safari.
What's missing in WPT
The two relevant concerns are tested separately but never combined, and the frame/hole geometry is uncovered for both:
| Concern |
Existing coverage |
Gap |
| Hit-testing through clipped-out region |
css/css-masking/hit-test/* (via elementFromPoint) |
Only "solid" shapes; no frame/hole polygon |
| Frame/hole clip-path rendering |
css/css-masking/clip-path/clip-path-polygon-004/005.html |
Visual reftests only — no hit-test, no scroll |
| Wheel scroll passing through a non-hit layer |
pointerevents/pointer-events-none-skip-scroll*.html (via test_driver.Actions().scroll()) |
Only via pointer-events: none — never via clip-path |
| clip-path + scroll |
css/css-masking/clip-path/clip-path-scroll.html etc. |
Tests a clip-pathed element scrolling itself — not scroll-through from an overlay |
| Frame clip-path + wheel scroll-through to scroller beneath |
— |
Nothing (this bug) |
Work done so far
Branch: kbav/clip-path-frame-hit-test-scroll (commit 2ddc18b)
Added three tests in css/css-masking/hit-test/:
clip-path-hit-test-frame-hole.html — elementFromPoint over a frame clip-path. Frame points → clipped element; hole points → element beneath. Isolates where the bug is: if this passes but the scroll test fails, the bug is specifically in wheel-event dispatch/hit-testing for scroll, not in elementFromPoint.
clip-path-scroll-through-clipped-region.html — wheel scroll in the clipped-out corner of a solid diamond clip-path reaches the scroller beneath. Control/baseline for the case that already works in Safari.
clip-path-scroll-through-frame-hole.html — wheel scroll in the clipped-out hole of a frame clip-path reaches the scroller beneath. The bug case — expected to fail in Safari, pass elsewhere.
All three pass wpt lint.
Next steps
Notes
- The scroll tests use
test_driver.Actions().scroll(...) — the same mechanism the established pointerevents/pointer-events-none-skip-scroll* tests use.
- Each scroll test races the scroll event against a 3s
step_timeout so a failure produces a clear "timeout" assertion rather than a harness hang.
WEB_FEATURES.yml left untouched — these are behavioral/interaction tests, not the clip-path-boxes feature gate.
Summary
Suspected bug in Safari / WebKit: when an overlay using a CSS
clip-pathsits above a scrollable layer, wheel-scrolling in the clipped-out (invisible) region of the overlay passes through to the scroller beneath for "solid" clip-path shapes, but fails to pass through when the clip-path is a "frame" — i.e. the visible part is the outer border and the clipped-out part is an inner hole (a self-touching polygon subpath, default nonzero fill).In the frame case, the inner hole is visually transparent, so per the hit-testing algorithm that determines wheel/pointer event targets it should be transparent to hit-testing as well — and wheel scroll there should reach the scroller beneath, just as it does for the clipped-out corners of a solid shape. In Safari it does not.
Repro shape (frame)
The user sees a semi-transparent blue frame around the content; the inner 50% is fully clear (clipped out). Wheel-scrolling inside that clear inner area does not reach the overflowing layer beneath in Safari.
What's missing in WPT
The two relevant concerns are tested separately but never combined, and the frame/hole geometry is uncovered for both:
css/css-masking/hit-test/*(viaelementFromPoint)css/css-masking/clip-path/clip-path-polygon-004/005.htmlpointerevents/pointer-events-none-skip-scroll*.html(viatest_driver.Actions().scroll())pointer-events: none— never via clip-pathcss/css-masking/clip-path/clip-path-scroll.htmletc.Work done so far
Branch:
kbav/clip-path-frame-hit-test-scroll(commit 2ddc18b)Added three tests in
css/css-masking/hit-test/:clip-path-hit-test-frame-hole.html—elementFromPointover a frame clip-path. Frame points → clipped element; hole points → element beneath. Isolates where the bug is: if this passes but the scroll test fails, the bug is specifically in wheel-event dispatch/hit-testing for scroll, not inelementFromPoint.clip-path-scroll-through-clipped-region.html— wheel scroll in the clipped-out corner of a solid diamond clip-path reaches the scroller beneath. Control/baseline for the case that already works in Safari.clip-path-scroll-through-frame-hole.html— wheel scroll in the clipped-out hole of a frame clip-path reaches the scroller beneath. The bug case — expected to fail in Safari, pass elsewhere.All three pass
wpt lint.Next steps
clip-path-scroll-through-frame-hole.html(and check whetherclip-path-hit-test-frame-hole.htmlpasses or fails — that pinpoints the bug's location)wpt run, browser drivers, etc.)link rel="bug"to the testsweb-platform-tests/wpt(no PR yet)Notes
test_driver.Actions().scroll(...)— the same mechanism the establishedpointerevents/pointer-events-none-skip-scroll*tests use.step_timeoutso a failure produces a clear"timeout"assertion rather than a harness hang.WEB_FEATURES.ymlleft untouched — these are behavioral/interaction tests, not theclip-path-boxesfeature gate.