You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular Material 18 SideNav autosize失效:折叠时宽度无法自适应

解决mat-sidenav隐藏文字后宽度无法自动适配的问题

问题核心

在mode="side"模式下,mat-sidenav的autosize属性不会自动监听内部元素的显示/隐藏变化来调整宽度,再加上mat-nav-list默认布局会预留空间,导致折叠侧边栏后宽度仍保持固定。

具体解决方案

1. 绑定动态状态并手动触发侧边栏重计算

先获取mat-sidenav实例,切换展开状态时强制触发宽度重计算,同时通过类控制布局:

修改HTML代码:

<mat-sidenav-container autosize="true">
    <mat-sidenav #sidenav mode="side" opened [ngClass]="{'sidenav-collapsed': !isExpanded}">
        <mat-nav-list>
            <mat-list-item (click)="toggleSidenav()">
                <mat-icon mat-list-icon class="chevron-button" [ngClass]="{ rotated: isExpanded }">chevron_right</mat-icon>
            </mat-list-item>

            @for (item of menuItems; track $index) {
                <mat-list-item [routerLink]="item.path">
                    <mat-icon matListItemIcon>{{ item.data?.['icon'] || 'default_icon' }}</mat-icon>
                    <span *ngIf="isExpanded" class="menu-item">{{ item.title }}</span>  
                </mat-list-item>
            }
        </mat-nav-list>
    </mat-sidenav>
    <mat-sidenav-content>
        <router-outlet></router-outlet>
    </mat-sidenav-content>
</mat-sidenav-container>

修改TS代码:
添加视图引用获取侧边栏实例,实现切换方法并触发宽度重计算:

import { CommonModule } from '@angular/common';
import { ChangeDetectionStrategy, Component, ViewChild } from '@angular/core';
import { routes } from '../../app.routes';
import { RouterModule } from '@angular/router';
import { MatSidenav, MatSidenavModule } from '@angular/material/sidenav';
import { MatButtonModule } from '@angular/material/button';
import { MatRadioModule } from '@angular/material/radio';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatIconModule } from '@angular/material/icon';
import { MatListModule } from '@angular/material/list';
import { MatToolbarModule } from '@angular/material/toolbar';

@Component({
  selector: 'app-side-menu',
  standalone: true,
  imports: [
    CommonModule,
    RouterModule, 
    MatButtonModule, 
    MatRadioModule, 
    FormsModule, 
    ReactiveFormsModule,
    MatSidenavModule, 
    MatIconModule,
    MatListModule,
    MatToolbarModule
  ],
  templateUrl: './side-menu.component.html',
  styleUrl: './side-menu.component.css',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SideMenuComponent {
  @ViewChild('sidenav') sidenav!: MatSidenav;

  public menuItems = routes
    .map( route => route.children ?? [] )
    .flat()
    .filter( route => route?.path )
    .filter( route => !route.path?.includes(':') )

  isExpanded: boolean = true;

  toggleSidenav() {
    this.isExpanded = !this.isExpanded;
    // 延迟触发,确保DOM更新后再计算宽度
    setTimeout(() => {
      this.sidenav.resize();
    }, 0);
  }
}

2. 添加CSS控制折叠状态布局

定义折叠时的侧边栏和列表样式,避免多余留白:

:host {
  display: block;
}

mat-sidenav-container {
  height: 100%;
}

.menu-item {
  margin-left: 8px;
}

.chevron-button {
  transition: 300ms ease-in-out;
  transform: rotate(0deg);
}

.chevron-button.rotated {
  transform: rotate(180deg);
}

/* 折叠状态样式 */
.sidenav-collapsed {
  width: fit-content !important;
  min-width: 60px; /* 保证图标完整显示 */
}

.sidenav-collapsed mat-nav-list {
  padding: 0;
}

.sidenav-collapsed mat-list-item {
  justify-content: center;
}

3. 适配OnPush变更检测策略

因为组件用了ChangeDetectionStrategy.OnPush,切换isExpanded后通过setTimeout确保DOM更新完成再调用resize,保证视图同步更新。

生效原理

  • sidenav.resize()强制侧边栏重新计算宽度,配合autosize属性实现自适应
  • 折叠状态的CSS消除默认布局的多余空间,让宽度贴合内容
  • 手动触发resize解决了mode="side"下自动监听内部元素变化失效的问题

内容的提问来源于stack exchange,提问作者Imad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 12:53:12