Skip to content

bug(sidenav): Auto-resizing is broken. #31641

@mazeneko

Description

@mazeneko

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

v16

Description

Auto-resizing has been broken since Angular Material v17 due to the container-width styling.

MatDrawerContainer#updateContentMargins() checks the width of MatDrawer.

updateContentMargins() {
// 1. For drawers in `over` mode, they don't affect the content.
// 2. For drawers in `side` mode they should shrink the content. We do this by adding to the
// left margin (for left drawer) or right margin (for right the drawer).
// 3. For drawers in `push` mode the should shift the content without resizing it. We do this by
// adding to the left or right margin and simultaneously subtracting the same amount of
// margin from the other side.
let left = 0;
let right = 0;
if (this._left && this._left.opened) {
if (this._left.mode == 'side') {
left += this._left._getWidth();
} else if (this._left.mode == 'push') {
const width = this._left._getWidth();
left += width;
right -= width;
}
}
if (this._right && this._right.opened) {
if (this._right.mode == 'side') {
right += this._right._getWidth();
} else if (this._right.mode == 'push') {
const width = this._right._getWidth();
right += width;
left -= width;
}
}
// If either `right` or `left` is zero, don't set a style to the element. This
// allows users to specify a custom size via CSS class in SSR scenarios where the
// measured widths will always be zero. Note that we reset to `null` here, rather
// than below, in order to ensure that the types in the `if` below are consistent.
left = left || null!;
right = right || null!;
if (left !== this._contentMargins.left || right !== this._contentMargins.right) {
this._contentMargins = {left, right};
// Pull back into the NgZone since in some cases we could be outside. We need to be careful
// to do it only when something changed, otherwise we can end up hitting the zone too often.
this._ngZone.run(() => this._contentMarginChanges.next(this._contentMargins));
}
}

However, the MatDrawer's width is fixed due to container-width styling.
As a result, the content margins always end up being the same value.

I guess adding width:auto to the host style of MatDrawer when autosize is specified could restore the behavior.

For example:
'[style.width]': '(!_container && _container.autosize) ? "auto" : null', on

host: {
'class': 'mat-drawer',
// must prevent the browser from aligning text based on value
'[attr.align]': 'null',
'[class.mat-drawer-end]': 'position === "end"',
'[class.mat-drawer-over]': 'mode === "over"',
'[class.mat-drawer-push]': 'mode === "push"',
'[class.mat-drawer-side]': 'mode === "side"',
// The styles that render the sidenav off-screen come from the drawer container. Prior to #30235
// this was also done by the animations module which some internal tests seem to depend on.
// Simulate it by toggling the `hidden` attribute instead.
'[style.visibility]': '(!_container && !opened) ? "hidden" : null',
// The sidenav container should not be focused on when used in side mode. See b/286459024 for
// reference. Updates tabIndex of drawer/container to default to null if in side mode.
'[attr.tabIndex]': '(mode !== "side") ? "-1" : null',
},

Reproduction

Reproduced the Angular Material docs example:

It still works on v16:

Expected Behavior

Auto-resizing should work.

Actual Behavior

Auto-resizing is not work.

Environment

  • Angular: v17~v20
  • CDK/Material: v17~v20
  • Browser(s): Chrome 138.0.7204.169
  • Operating System (e.g. Windows, macOS, Ubuntu): Windows

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2The issue is important to a large percentage of users, with a workaroundarea: material/sidenavregressionThis issue is related to a regression

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions