Skip to content

clip-path frame/hole: wheel scroll-through to scroller beneath (suspected Safari/WebKit bug) #1

Description

@kbav

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: nonenever 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/:

  1. clip-path-hit-test-frame-hole.htmlelementFromPoint 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.
  2. 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.
  3. 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

  • Run tests against Chrome/Chromium and ensure they all pass
  • Run tests against Safari/WebKit and confirm the intended failure on clip-path-scroll-through-frame-hole.html (and check whether clip-path-hit-test-frame-hole.html passes or fails — that pinpoints the bug's location)
  • WPT repo setup / docs reading to run tests locally (wpt run, browser drivers, etc.)
  • Once validated, file the upstream WebKit bug and add link rel="bug" to the tests
  • Open PR upstream to web-platform-tests/wpt (no PR yet)

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions