I am working on an Angular 17 project with a Tailwind CSS-styled sidebar. The expand/collapse functionality works as intended, but the animation is not as smooth as I would like. There is a noticeable "jump" in the animation, which disrupts the smooth transition I aim for. Ideally, the animation should smoothly transition from the top to bottom (and vice versa) without glitches. Showcase of the problem: https://i.imgur.com/4RpEwYv.gif My HTML Code: <div class="flex h-screen bg-white"> <aside class="w-72 bg-gray-900 shadow-lg flex flex-col"> <!-- Navigation --> <nav class="p-4 pl-0 overflow-y-auto"> @for (group of navigation; track $index) { <div class="mb-2" [class.pb-3]="$index != navigation.length - 1"> <div class="flex flex-col"> <div class="flex items-center justify-between pl-2 pr-0 cursor-pointer gap-2 w-[104%]" (click)="toggleGroup(group.category)"> <div> <h3 class="px-0 mb-0 text-xs font-semibold text-gray-500 uppercase tracking-wider text-{{group.color}}-gradient"> {{ group.category }} </h3> <p class="text-xs text-gray-500 mb-0">{{ group.description }}</p> </div> </div> </div> <div class="mt-2 space-y-1 overflow-hidden" [@expandCollapse]="expandedGroups[group.category] ? 'expanded' : 'collapsed'"> <div class="space-y-1"> <!-- Show only 3 pages if group is not expanded & be able to expand it --> @for (page of (expandedGroups[group.category] ? group.pages : group.pages.slice(0, 3)); track $index) { <a [routerLink]="page.redirect_url" class="flex items-center p-2 !text-slate-400 hover:bg-gray-500 rounded-lg transition-none hover:!text-white"> <div class="w-6 flex-shrink-0"> <fa-icon [icon]="page.icon"></fa-icon> </div> <span class="ml-3 text-[0.9rem]">{{ page.title }}</span> </a> } </div> </div> </div> } </nav> </aside> </div> TypeScript Code with Angular animation part: @Component({ selector: 'app-dashboard', standalone: true, imports: [ NgOptimizedImage, RouterLink, FaIconComponent, ], templateUrl: './dashboard.component.html', styleUrl: './dashboard.component.scss', animations: [ trigger('expandCollapse', [ state('collapsed', style({ height: '86px', overflow: 'hidden', opacity: 1 })), state('expanded', style({ height: '*', overflow: 'hidden', opacity: 1 })), transition('expanded => collapsed', [ style({ height: '*' }), animate('300ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({ height: '96px' }) ) ]), transition('collapsed => expanded', [ style({ height: '96px' }), animate('300ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({ height: '*' }) ) ]) ]) ] }) export class DashboardComponent { // it is filled, but commented out navigation = [] expandedGroups: { [key: string]: boolean } = {}; toggleGroup(category: string) { this.expandedGroups[category] = !this.expandedGroups[category]; } constructor() { this.navigation.forEach(group => { this.expandedGroups[group.category] = false; }); } Continue reading...