Skip to content

[popover] Scrolls page to top when opened (portal + focus interaction) #4520

@ramonmalcolm10

Description

@ramonmalcolm10

Description

When a Popover is opened, the page scrolls to the top. This happens because the popover content is portaled to the end of <body> via PopoverPrimitive.Portal, and FloatingFocusManager calls focus() on the popup element without { preventScroll: true }. The browser's default focus behavior scrolls the focused element into view, jumping to the portaled content at the bottom of the DOM.

Steps to Reproduce

  1. Create a page with enough content to scroll
  2. Place a Popover component lower on the page (e.g., inside a form)
  3. Use the default portal behavior (PopoverContent wraps with Portal + Positioner + Popup)
  4. Click the popover trigger
  5. Observe: page scrolls to the top

Expected Behavior

The popover should open positioned near its trigger without causing any page scroll.

Actual Behavior

The page scrolls to the top when the popover opens. On the second open (if you scroll back and click again), it may not scroll because the portaled element is already mounted and focused in place.

Root Cause

In PopoverPopup.js, the popup is rendered inside a FloatingFocusManager:

<FloatingFocusManager
  context={floatingContext}
  modal={focusManagerModal}
  initialFocus={resolvedInitialFocus}
  // ...
>

When FloatingFocusManager moves focus to the popup (or an element inside it), the browser's native element.focus() scrolls to make the element visible. Since the portal appends to <body>, this scrolls to the top/bottom of the page.

Setting modal={false} on the Popover root does not fix the issue.

Environment

  • @base-ui/react: 1.3.0
  • React: 19.2.4
  • Browser: Chrome 146
  • OS: macOS

Workaround

None found so far. Setting modal={false} does not prevent the scroll.

Suggested Fix

The focus() calls within FloatingFocusManager (or the initial focus logic in PopoverPopup) should use element.focus({ preventScroll: true }) when the popup is portaled, to avoid triggering browser scroll behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    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