Reputation: 2674
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
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
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
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
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
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