Skip to content

bug(cdk/drag-drop): drag preview shows a scrollbar because the UA popover overflow style is never reset #33551

Description

@byrondover

Is this a regression?

  • Yes, this behavior used to work in the previous version

The previous version in which this bug was not present was

17.3.5 (previews became native popovers in 17.3.6/17.3.7)

Description

Since v17.3.7 the drag preview is rendered as a native popover — preview.setAttribute('popover', 'manual') + showPopover() — which is great for stacking, but it also opts the preview into the spec-mandated UA popover styles.

Per the WHATWG HTML rendering section, every [popover] element gets:

[popover] {
  position: fixed;
  inset: 0;
  width: fit-content;
  height: fit-content;
  margin: auto;
  border: solid;
  padding: 0.25em;
  overflow: auto;      /* 👈 */
  color: CanvasText;
  background-color: Canvas;
}

CDK already neutralizes most of that block in src/cdk/drag-drop/resets.scss:

@layer cdk-resets {
  .cdk-drag-preview {
    background: none;
    border: none;
    padding: 0;
    color: inherit;

    // Chrome sets a user agent style of `inset: 0` which combined
    // with `align-self` can break the positioning (see #29809).
    inset: auto;
  }
}

…but overflow was never included, so every drag preview is silently a scroll container (getComputedStyle(preview).overflow === 'auto').

That stays invisible only while the preview's content happens to fit its box exactly. CDK sizes the default preview with inline width/height measured from the original element (matchElementSize), so any app styling on .cdk-drag-preview that changes the box — a 1px border, some padding — combined with the near-universal * { box-sizing: border-box } reset shrinks the content box below the measured content.

The result is 1–2px of scrollable overflow, and a scrollbar renders on the floating "photo" of the dragged element and rides along with the pointer. The scroll container exists in every engine that I tested (Firefox ships the identical UA rule, citing the same spec anchor); Chromium's scrollbar presentation just makes it the most visible.

Image

Related issues:

Following the #29809 pattern, it looks like the reset could be completed with an explicit overflow declaration in the same resets.scss block (e.g. overflow: clip).

Workaround:

For anyone hitting this today — simply complete the reset app-side:

.cdk-drag-preview {
  overflow: clip;
}

Reproduction

StackBlitz link: https://stackblitz.com/edit/components-issue-starter-wr9aehf8?file=src%2Fglobal_styles.css

Steps to reproduce:

  1. Open the StackBlitz preview in a Chromium browser (Chrome/Edge) and drag any row, holding it mid-drag.
  2. Look at the right edge of the floating preview: a vertical scrollbar is rendered. The console also logs the preview's computed overflow (auto auto) and its overflow geometry (scrollHeight > clientHeight) mid-drag.

The repro is the docs sorting example plus two commonplace styles: a global * { box-sizing: border-box } reset and a 1px border on .cdk-drag-preview — the same effective styling the docs example produced on its preview when #29419 was filed.

Even with no author styling at all, the preview is still a scroll container (getComputedStyle reports overflow: auto); the border merely gives the overflow a visible 1–2px to show.

Expected Behavior

The drag preview should paint exactly like the dragged element (plus any intentional .cdk-drag-preview styling) and should never be a scroll container. The UA popover styles should be fully neutralized by @layer cdk-resets the way background, border, padding, color, and inset already are — so an author border or padding on the preview can never produce scrollbars mid-drag.

Actual Behavior

getComputedStyle(document.querySelector('.cdk-drag-preview')).overflow reports auto mid-drag — the UA popover style survives the reset. With a 1px preview border under box-sizing: border-box, measured while dragging the second row of the repro: scrollHeight 48 vs clientHeight 47, with the rendered scrollbar consuming a 15px gutter (offsetWidth 418 vs clientWidth 401 + 2px of borders).

Image

Environment

  • Angular: 22.0.7
  • CDK/Material: 22.0.5 (still reproducible against mainresets.scss has no overflow reset)
  • Browser(s): Chrome 150 (any Chromium; Firefox has the same UA rule but paints no classic scrollbar)
  • Operating System (e.g. Windows, macOS, Ubuntu): macOS

Metadata

Metadata

Assignees

Labels

P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgentarea: cdk/drag-dropgemini-triagedLabel noting that an issue has been triaged by gemini

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions