Description
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:
- Go to official select documentation example "Select with reset option" https://material.angular.io/components/select/examples#select-reset
- Scroll such that the example mat-select is at the bottom of the page so that the overlay will open towards the top
- Open mat-select
- 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