angular: [Animations] toggle state with `display: 'none'` doesn't work on Safari

šŸž bug report

Affected Package

The issue is caused by package @angular/animations

Is this a regression?

Yes, the previous version in which this bug was not present was: 7.2.7

Description

When using animation state with `display: 'none'` the animation does not fire/finish on Safari. It seems to be related to #28911 .

šŸ”¬ Minimal Reproduction

https://stackblitz.com/edit/angular-v6-animations-txqyvd After click on ā€œfadeā€ button, two texts should be shown (without actual ā€œfade inā€ animation, they should just appear), what works perfectly fine in Chrome, Firefox and IE/Edge on Linux/Windows.

šŸŒ Your Environment

Angular Version:

Angular: 7.2.8

Anything else relevant?

Safari on macOS and iPad

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 27
  • Comments: 21 (1 by maintainers)

Most upvoted comments

I have the same problem in IE11 in Angular 8.1.0: The animation seems to get stuck in a ā€œanimation-play-state: running;ā€ state. Replacing ā€œdisplay: none;ā€ with ā€œheight: 0;ā€ seems to fix the problem.

@james-criscuolo, @dawda92 the diff is presence of display: 'none' in Stackblitz example and itā€™s absence in Materialā€™s example
Angular 8 no longer support display property in animations. As I understood.

Also, to get expanded row hided on default state, itā€™s required to add overflow: hidden as in Materialā€™s example

.example-element-detail {
  overflow: hidden;
  display: flex;
}

This works to me (take a note for an additional void state)

    trigger('detailExpand', [
      state('collapsed, void', style({ height: '0px', minHeight: '0' })),
      state('expanded', style({ height: '*' })),
      transition('expanded <=> void, expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
    ])

@gizmodus @AmebaBrain I had the same issue with version 8.1.3 Animations containing display:block <=> display:none were not working on Safari Mac and iOS.

Solved by display property and using height:'*' <=> height:0 in animation states.

I would never get back the 2 weeks that I spent solving this but thank you very much, everyone

Working code:

trigger('displayAnim', [
        state('true', style({
            'height': '*', 'opacity': '1'
        })),
        state('false', style({
            'height': '0', 'opacity': '0'
        })),
        transition('true => false', [group([
            animate('200ms ease-in-out', style({
                'opacity': '0'
            })),
            animate('200ms ease-in-out', style({
                'height': '0'
            })),
            // animate('200ms ease-in-out', style({
            //     'display': 'none'
            // }))
        ]
        )]),
        transition('false => true', [group([
            // animate('200ms ease-in-out', style({
            //     'display': 'block'
            // })),
            animate('200ms ease-in-out', style({
                'height': '*'
            })),
            animate('200ms ease-in-out', style({
                'opacity': '1'
            }))
        ]
        )])
    ]),

After trying several of the solution suggested here. Setting the height affected my transitions in a way that I didnā€™t want and display: block and display: none was required for my UI. I found that this one worked best for my case.

// ...component.ts
@Component({  // ...
animations: [
   trigger('backdropAnimation', [
     state('false', style({
       'opacity': '0',
     })),
     state('true', style({
       'opacity': '1',
     })),
     transition(
       'false => true',
       animate('500ms ease-out')
     ),
     transition(
       'true => false',
       animate('400ms ease-in')
     ),
   ]),

// ...

 public isAnimationOptionsStateOpen = false;
 public backdropDisplay: 'block'|'none' = 'none';

// ...

 public backdropStart(): void {
   this.backdropDisplay = 'block';
 }

 public backDropDone(): void {
   this.backdropDisplay = (this.isAnimationOptionsStateOpen ? 'block' : 'none');
 }
// ...component.html
<div
      (@backdropAnimation.start)="backdropStart()"
      (@backdropAnimation.done)="backDropDone()"
      [@backdropAnimation]="isAnimationOptionsStateOpen"
      [ngClass]="['backdrop']"
      [ngStyle]="{'display': backdropDisplay}">
</div>

Any update on this part? Iā€™m facing the same problem.

I have this issue in Chrome/safari in ios 12.1.4 with Angular 8.1. It works on Safari if the experimental feature for web animation is turned on.

@simeyla The example was prepared very quickly from already existing stackblitz to show that nothing happens in the Safari. I know that it is actually only fading out and itā€™s intended.

@Michsior14 Iā€™m facing the same problem, where my animated container contains a mat-progress-bar so I donā€™t want to leave it animating the whole time my application is running!

The problem is I donā€™t think your example really works very well on Chrome either.

I changed your stackblitz to use longer delays (of 2 or 4 seconds). When you click the ā€œFadeā€ button to fade in you donā€™t actually see anything fading in - it just jumps to being visible after 2 seconds or 4 seconds.

So while there does indeed seem to be a regression in Safari - because it just flat doesnā€™t work - thereā€™s a better way to do the display: none thing like this:

The difference being the ā€˜blockā€™ state is set on the transition. This works in Safari.

 trigger('activeAnimation',
        [
            state('inactive', style({ 'height': '0px', 'opacity': '0', 'display': 'none' })),
            state('active', style({ 'height': '30px', 'opacity': '1' })),

            transition('inactive => active', [
                style({ 'display': 'block' }),
                animate('5000ms ease-in')
            ]),

            transition('active => inactive', [
                animate('5000ms ease-in')
            ])
        ]),

Stackblitz

However I canā€™t figure out why the animation of the mat-progress bar is completely messed up - but the panel animates just fine.

Still facing this issue at 7.2.14. 7.2.7 is the last version working, as stated above.