0

Using Angular Material (version 10), I would like to animate a mat-card so that it vertically expands to its full height when the page loads.

I have tried some tests just with the hover event (if this works, I will then work on how to apply the transition upon page load - this is another story), with the following CSS:

.test-anim {
  height: 0!important;
  transition: height 2s ease !important;
  &:hover {
    height: 100% !important;
  }
}
<mat-card class="test-anim">
  [some content...]
</mat-card>

Unfortunately this does not work:

  1. when I hover the mat-card, the card expends directly from 0 to 100%, but with no transition at all. And btw, when I try to set the height manually from Chrome Developer Tools, I realize that any intermediate percentage (e.g. 50%) seems to be taken as 100%. Only 0% makes a difference with 100%. (However, the animation works with opacity instead of height, and replacing 100% with 1).

  2. I cannot use px values in the transition, because the actual height of the mat-card could vary depending on the data being displayed.

  3. even though I would use px values for the transition, it would still not fully work: when I manually set the height in pixels (eg '30px') from Chrome Developer Tools, the card itself is actually sized properly, BUT its content is displayed outside of the card (I would have expected some kind of clipping of the mat-card content, by the mat-card itself).

Could you please help me? Many thanks!

bfredo123
  • 462
  • 1
  • 8
  • 20

1 Answers1

2

I think it would be easier for you to take the benefit of the Angular's animation API.

What you need to do is:

  1. Set the height of the mat-card to 100% (or flex:1, or something else based on your parent / requirements).
  2. Define the animation on your component
  3. Apply the animation to the HTML element you want to (e.g. mat-card)
  4. Trigger the animation.

Here is a working stackblitz I've forked from mat-card documentation and to which I've added animation.

To expand upon it:

Add class to the element:

<mat-card class="example-card">

Define the class:

 .example-card {
   height: 100%;
 }

Define the animation:

@Component({
  selector: 'card-fancy-example',
  templateUrl: 'card-fancy-example.html',
  styleUrls: ['card-fancy-example.css'],
  animations: [
    trigger('bodyExpansion', [
      state('collapsed, void', style({ height: '0px', visibility: 'hidden', overflow: 'hidden' })),
      state('expanded', style({ height: '*', visibility: 'visible', overflow: '*' })),
      transition(
        'expanded <=> collapsed, void => collapsed, void => expanded',
        animate('1000ms cubic-bezier(0.4, 0.0, 0.2, 1)')
      ),
    ]),
  ],
})

Apply the animation to html element:

<mat-card class="example-card" [@bodyExpansion]="state">

Define the state variable and update it "after page loads" (I've used after content init, might mean something else to you).

  state: 'expanded' | 'collapsed' = 'collapsed';

  ngAfterContentInit(): void {
    this.state = 'expanded';
  }

And basically that's it. You should understand it after you fully read the whole documentation I've linked.

TotallyNewb
  • 3,884
  • 1
  • 11
  • 16
  • Wow, thank you so much @TotallyNewb. I will have a closer look in a few days when at my desk, but the stackblitz seems to address the child issue pretty well! One remark however: the card seems to extend the full page height, instead of just taking the height it needs (as it would be by default without any animation), right? (For what I need, the page has a series of elements, so it would be inconvenient that each one take the extra page height, and then make the next ones invisible without scrolling). – bfredo123 Feb 03 '22 at 15:27
  • 1
    Just remove the height: 100% from the `.example-card` (or remove the class binding altogether). I've misunderstood the part "animate a mat-card so that it vertically expands to its full height when the page loads" - where I assumed "it" was the whole page and not mat-card contents. You might tinker with mat-content animations as well, and the overflow settings to make it feel "smoother" during the resizing. – TotallyNewb Feb 03 '22 at 21:11
  • Thank you again! I have indeed "improved" it a little (I think), because so far, at the middle of the animation, some elements become completely visible and overflow the card. I guess this is due to the 'overflow' being 'visible' in the end. By having it 'hidden' all time, it is closer to what I was expecting. Changes here: https://stackblitz.com/edit/angular-69nrdm-sykevk?file=src%2Fapp%2Fcard-fancy-example.ts – bfredo123 Feb 05 '22 at 09:09