Moshe
Moshe

Reputation: 2674

Elevate md-card in angular material

According to the Material Design spec:

On desktop, cards can have a resting elevation of 0dp and gain an elevation of 8dp on hover.

How can I create this animated effect using Angular Material 2?

I have considered doing this with (hover)= and with animations. I don't really care for the approach, I would prefer for it to elevate on hover. The reason for this, I'm using cards as buttons in my UI.

Upvotes: 5

Views: 14678

Answers (5)

millenion
millenion

Reputation: 1907

If some people are looking for a pure scss solution using material mixins:

(credits to @Nehal) for this beautiful transition that i used in the following solution:

.elevate-on-hover {
  transition: background .4s cubic-bezier(.25,.8,.25,1),box-shadow 280ms cubic-bezier(.4,0,.2,1);
  &:hover {
    @include mat.elevation(4)
  }

  &--2 {
    &:hover {
      @include mat.elevation(2)
    }
  }

  &--4 {
    &:hover {
      @include mat.elevation(4)
    }
  }

  &--8 {
    &:hover {
      @include mat.elevation(8)
    }
  }
}

You can use it like this:

<mat-card class="elevate-on-hover elevate-on-hover--8">

   // stuff...
</mat-card>

Upvotes: 1

Ashkan
Ashkan

Reputation: 421

another way of doing this is that you get material elevation classes in you style file and use it there. for example in my scss file i have:

@use '~@angular/material' as mat;

.my-card {
  // ...some-custom-styles
  &:hover {
    @include mat.elevation(12);
  }
}

Upvotes: 3

Taylor G
Taylor G

Reputation: 898

A directive is re-usable and configurable, and can be applied to any number of elements. Create the directive, and reference it in your module's declarations.

This directive adds and removes the elevation class when the user's mouse enters or leaves the element.

import { Directive, ElementRef, HostListener, Input, Renderer2, OnChanges, SimpleChanges } from '@angular/core';

@Directive({
  selector: '[appMaterialElevation]'
})
export class MaterialElevationDirective implements OnChanges {

  @Input()
  defaultElevation = 2;

  @Input()
  raisedElevation = 8;

  constructor(
    private element: ElementRef,
    private renderer: Renderer2
  ) {
    this.setElevation(this.defaultElevation);
  }

  ngOnChanges(_changes: SimpleChanges) {
    this.setElevation(this.defaultElevation);
  }

  @HostListener('mouseenter')
  onMouseEnter() {
    this.setElevation(this.raisedElevation);
  }

  @HostListener('mouseleave')
  onMouseLeave() {
    this.setElevation(this.defaultElevation);
  }

  setElevation(amount: number) {
    const elevationPrefix = 'mat-elevation-z';
    // remove all elevation classes
    const classesToRemove = Array.from((<HTMLElement>this.element.nativeElement).classList)
      .filter(c => c.startsWith(elevationPrefix));
    classesToRemove.forEach((c) => {
      this.renderer.removeClass(this.element.nativeElement, c);
    });

    // add the given elevation class
    const newClass = `${elevationPrefix}${amount}`;
    this.renderer.addClass(this.element.nativeElement, newClass);
  }
}

Then the directive can be applied to an element, with optional input properties.

<mat-card appMaterialElevation [defaultElevation]="variableHeight" raisedElevation="16">
    <mat-card-header>
        <mat-card-title>Card Title</mat-card-title>
    </mat-card-header>
    <mat-card-content>
        <p>
            This card changes elevation when you hover over it!
        </p>
    </mat-card-content>
</mat-card>

See this demo StackBlitz.

Upvotes: 10

Nodarii
Nodarii

Reputation: 984

As for me it would be better to use predefined css classes for it. And toggle this class when user hovers over md-card. To change the evelavtion use mat-elevation-z{{elevationValue}}

Upvotes: 2

Nehal
Nehal

Reputation: 13307

To change elevation of md-card, create a class like following:

.z-depth:hover {
    box-shadow: 0 8px 8px 8px rgba(0,0,0,.2), 0 8px 8px 0 rgba(0,0,0,.14), 0 8px 8px 0 rgba(0,0,0,.12) !important;
    transform: translate3d(0,0,0);
    transition: background .4s cubic-bezier(.25,.8,.25,1),box-shadow 280ms cubic-bezier(.4,0,.2,1);
}

You can change the box-shadow numbers to find the exact elevation you are looking for.

Plnkr demo.

Upvotes: 8

Related Questions