bug(select): exit fade resets opacity before deferred panel removal with legacy animations
Les mainteneurs répondent en général sous 1 jour
@crisbeto y travaille déjà.
Depuis le 25/9/2026.
Évaluation
- Difficulté
- 4/5
- Temps estimé
- 3-5 jours
- Accessibilité débutants
- 56/100
- Type d'issue
- Bug
- Clarté
- Plutôt claire
- Activité
- Active
- Stack technique
- angular, typescript
- Domaine
- frontend
Piste de recherche
Start with the supplied isolated reproduction and inspect the Material select exit animation styles and the detachment methods mentioned in the issue. Run the Chromium reproduction with and without the legacy trigger, then verify that the panel retains its transparent final state until DOM removal without regressing the exit fade.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Is this a regression?
- Yes, this behavior used to work in the previous version
Unknown. It was noticed recently, but I have not established the first affected Angular/Material or Chromium version.
Description
A mat-select panel can become opaque again after its closing fade has finished, before Angular actually removes its DOM node. The transient panel is visible as a flash in Chromium.
A reduced example uses only Angular, Material's prebuilt azure-blue theme, a standalone select, zoneless change detection, and provideAnimationsAsync(). Binding an empty legacy animation trigger on the root component activates the legacy animation renderer and reproduces the delayed removal / opacity rebound. There is no application filter logic, routing, custom select animation, or overlay configuration in this reduced case.
Reproduction
Complete isolated source and one-click StackBlitz launcher: https://gist.github.com/EthanSK/056299e55311004487e48e0a6f66b203
REPL link limitation: The official StackBlitz SDK launcher opens the complete project, but its anonymous generated URL is session-scoped until saved to an account, so the gist is the persistent entry point. I verified that the launcher opens the expected project files and begins dependency installation; remote dependency installation and browser preview have not completed in this test. CodeSandbox’s angular-cli preset unconditionally requires zone.js even though this reproduction is zoneless, and its generic Node sandbox did not start an Angular CLI preview. I did not add Zone.js because that would change the relevant configuration. The same component/providers were actually run and measured in a local Angular CLI build using the tested package versions.
- Run the supplied example in Chromium 153. Tested with 153.0.8010.48 on macOS 26.6.2.
- Open Choice, let the opening animation finish, then press Escape without changing the value. Repeat, leaving the page otherwise idle.
- For measurements, enable the optional diagnostics described in the reproduction. They sample
animationend, its microtask, a zero-delay timer, and actual DOM disconnection. They do not run a continuousrequestAnimationFrameloop. - Compare with the empty
animations: [trigger(...)]declaration and matching template binding removed, keepingprovideAnimationsAsync()configured. - Restore the trigger and add only the exit
animation-fill-mode: forwardsrule below.
Minimal component/provider configuration:
@Component({
selector: 'app-root',
imports: [MatFormFieldModule, MatSelectModule],
animations: [trigger('activateLegacyRenderer', [])],
template: `
<h1 @activateLegacyRenderer>Material select close reproduction</h1>
<mat-form-field>
<mat-label>Choice</mat-label>
<mat-select value="one">
<mat-option value="one">One</mat-option>
<mat-option value="two">Two</mat-option>
<mat-option value="three">Three</mat-option>
</mat-select>
</mat-form-field>
`,
})
class SelectReproductionComponent {}
bootstrapApplication(SelectReproductionComponent, {
providers: [provideZonelessChangeDetection(), provideAnimationsAsync()],
});
Expected Behavior
The select remains transparent after its exit fade completes and until its DOM is removed.
Actual Behavior
The exit animation has fill mode none. When it finishes, computed opacity returns to 1 while the panel is still connected. The legacy animation renderer defers actual node removal, leaving an opportunity for the opaque panel to be painted.
Repeated measurements of the reduced example:
| Configuration | Result at the zero-delay callback after animationend |
|---|---|
| Zoneless + activated legacy renderer + default CDK overlay | 10/10 still connected, opacity 1 |
Same, with usePopover: false |
10/10 still connected, opacity 1 |
| Remove the bound legacy trigger, retain async animation provider | 10/10 already disconnected |
| Restore trigger and apply forwards fill | 10/10 still connected, opacity 0 |
The baseline default-overlay animationend-to-removal interval was approximately 0.9–2.4 ms. Timing instrumentation can perturb scheduling; these measurements are not a frequency estimate of visible flashes. In the original application, consecutive browser screenshots captured a nearly transparent panel, then a fully opaque panel, then its removal. The reduced example reproduces the same connected/opaque state without application UI or styles.
A narrow workaround that preserves the fade and removal timing:
.mat-mdc-select-panel.mat-select-panel-animations-enabled.mat-select-panel-exit {
animation-fill-mode: forwards;
}
This also prevented the measured rebound in 23/23 matched filter closes in the original application, and restoring the original CSS restored the rebound in 10/10 closes. Material menus already retain their final fade state and did not show this rebound in six control closes.
Environment
- Angular core / animations / platform-browser: 21.2.10
- CDK / Material: 21.2.8
- Angular CLI / build: 21.2.8
- TypeScript: 5.9.3
- RxJS: 7.8.2
- Browser directly instrumented: Chromium 153.0.8010.48 (embedded browser)
- Also observed manually: Google Chrome 153.0.8010.52, including incognito
- Operating system: macOS 26.6.2
- Zoneless with
provideAnimationsAsync()and an active legacy animation trigger
Related issues and scope
- https://github.com/angular/components/pull/30456 addressed a related select-detachment problem. Its
markForCheck()change is already present in the tested version. - https://github.com/angular/angular/issues/58075 concerns zoneless / legacy-animation overlay cleanup and was closed by an earlier fix.
- Source inspection of Material 21.2.14 and 22.1.7 still shows the same no-fill exit and relevant detachment methods. Those newer versions have not been runtime-tested here.
Chromium 153 has animation scheduling changes, but a browser feature toggle / version bisect has not been performed. I am not claiming that Chrome 153 introduced the bug or that it is a Chromium standards violation. Filing here because the select exit loses its final opacity before removal; please redirect to Angular core if the deferred cleanup is the preferred place to address it.
- Langage dominant
- TypeScript
- Étoiles
- 25k
- Forks
- 6.8k
- Merge moyen
- 1 j 11 h
- PR mergées (30 j)
- 81
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Aucun modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de angular/components
-
bug(material/sort): hover hint arrow on an unsorted header shows the active sort direction, not the resulting direction after click.Peut-être pris @lekhmanrus l’a pris il y a 8 jours. Ouvertearea: material/sort gemini-triaged needs triage
Difficulté 2/5 1-3 heures Accessibilité débutants 70/100
angular/components#33933 ·
Les mainteneurs répondent en général sous 1 jour
-
bug(mat-date-picker): month shown twice in date pickerPeut-être pris @PreethiPantangi l’a pris il y a 25 jours. Ouvertearea: material/datepicker P4
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
angular/components#33763 · 2 commentaires · 3 réactions ·
Les mainteneurs répondent en général sous 1 jour
-
Bug in table.scss footer cell height: unset instead of footer row height unsetPeut-être pris @minwookshin l’a pris il y a 12 jours. Ouvertearea: material/table P4
Difficulté 1/5 Moins d'une heure Accessibilité débutants 88/100
angular/components#33709 · 1 commentaire ·
Les mainteneurs répondent en général sous 1 jour
-
docs-bug(Table): Add example with `rowspan`Peut-être pris @BHUVANSH855 l’a pris il y a 92 jours. Ouvertearea: material/table docs P4
Difficulté 2/5 1-3 heures Accessibilité débutants 72/100
angular/components#33455 ·
Les mainteneurs répondent en général sous 1 jour
-
bug(date-adapter): Misleading JSDoc for createDate returns typePeut-être pris @BHUVANSH855 l’a pris il y a 142 jours. Ouvertearea: material/core P3
Difficulté 1/5 Moins d'une heure Accessibilité débutants 78/100
angular/components#33059 · 2 commentaires ·
Les mainteneurs répondent en général sous 1 jour
Toutes les issues de angular/components
Issues similaires
-
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
apache/rocketmq-dashboard#6872 ·
Les mainteneurs répondent en général sous 3 jours
-
bug
Difficulté 2/5 1-3 heures Accessibilité débutants 70/100
fab-geocommuns/RNB-site#539 ·
Les mainteneurs répondent en général sous 2 jours
-
Guest multiview tile label leaks raw virtual-source-id "Whip" instead of the guest name / slot labelOuverte
Difficulté 2/5 1-3 heures Accessibilité débutants 62/100
Eyevinn/open-live-studio#211 ·
Les mainteneurs répondent en général sous 1 jour
-
documentation good first issue
Difficulté 2/5 Une demi-journée Accessibilité débutants 72/100
sujithputta02/Esapay#13 ·
-
Difficulté 2/5 1-3 heures Accessibilité débutants 65/100
ehmpathy/rhachet-roles-bhuild#468 ·
Les mainteneurs répondent en général sous 1 jour