Skip to content

bug(Select): Overlay scrolls to incorrect positions with keyboard navigation when mat-select overlay opens upwards #30974

Closed
@natascha-may

Description

@natascha-may

Is this a regression?

  • No.

Description

When navigating with keyboard navigation inside the selects overlay, the scroll position jumps to unexpected positions when the overlay is opened towards the top.

I debugged and found that the method _getOptionScrollPosition from mat-option returns an incorrect position. However, it may be fixed inside the mat-select code as well. I am not sure where the fix should happen, as I don't if the same behavior occurs elsewhere or if other side effects could be caused.

I was able to implement a workaround for myself by calling a custom scrolling method whenever the _keyManager emits a value in the change observable. The custom method is a copy of the original method _scrollOptionIntoView from mat-select which currently looks like this:

  /** Scrolls a particular option into the view. */
  _scrollOptionIntoView(index: number): void {
    const option = this.options.toArray()[index];

    if (option) {
      const panel: HTMLElement = this.panel.nativeElement;
      const labelCount = _countGroupLabelsBeforeOption(index, this.options, this.optionGroups);
      const element = option._getHostElement();

      if (index === 0 && labelCount === 1) {
        // If we've got one group label before the option and we're at the top option,
        // scroll the list to the top. This is better UX than scrolling the list to the
        // top of the option, because it allows the user to read the top group's label.
        panel.scrollTop = 0;
      } else {
        panel.scrollTop = _getOptionScrollPosition(
          element.offsetTop,
          element.offsetHeight,
          panel.scrollTop,
          panel.offsetHeight,
        );
      }
    }
  }

The fix in my workaround is that it passes element.offsetTop - panel.offsetTop as the optionOffset parameter instead of element.offsetTop when calling the original method _getOptionScrollPosition .

panel.scrollTop = _getOptionScrollPosition(
          element.offsetTop - panel.offsetTop,
          element.offsetHeight,
          panel.scrollTop,
          panel.offsetHeight,
        );
  }

Reproduction

Steps to reproduce:

  1. Go to official select documentation example "Select with reset option" https://material.angular.io/components/select/examples#select-reset
  2. Scroll such that the example mat-select is at the bottom of the page so that the overlay will open towards the top
  3. Open mat-select
  4. Press arrow key down
20250429-1015-17.7372275.mp4

Expected Behavior

The select does not scroll as the active option is visible.

Actual Behavior

The select scrolls down to an unexpected position such that the active option is now not visible.

Environment

  • Angular: 19.2.11
  • CDK/Material: 19.2.11
  • Browser(s): Edge, Firefox
  • Operating System (e.g. Windows, macOS, Ubuntu): Windows 11

Metadata

Metadata

Assignees

Labels

P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgentarea: material/select

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions