Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 701
Moshe Avatar asked Dec 03 '22 22:12

Moshe


2 Answers

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.

like image 97
Taylor G Avatar answered Dec 11 '22 17:12

Taylor G


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.

like image 45
Nehal Avatar answered Dec 11 '22 16:12

Nehal