diff --git a/src/components/button/_button-base.scss b/src/components/button/_button-base.scss
index 8c15c0f211bf..5d19e04293eb 100644
--- a/src/components/button/_button-base.scss
+++ b/src/components/button/_button-base.scss
@@ -1,6 +1,6 @@
@import "variables";
-@import "shadows";
+@import "elevation";
// TODO(jelbourn): This goes away.
@import "default-theme";
@@ -70,20 +70,20 @@ $md-mini-fab-padding: 8px !default;
%md-raised-button {
@extend %md-button-base;
+ @include md-elevation(1);
@include md-button-theme('color', default-contrast);
@include md-button-theme('background-color');
background-color: md-color($md-background, background);
- box-shadow: $md-shadow-bottom-z-1;
// Force hardware acceleration.
transform: translate3d(0, 0, 0);
// Animation.
transition: background $swift-ease-out-duration $swift-ease-out-timing-function,
- box-shadow $swift-ease-out-duration $swift-ease-out-timing-function;
+ md-elevation-transition-property-value();
&:active {
- box-shadow: $md-shadow-bottom-z-2;
+ @include md-elevation(2);
}
&.md-button-focus {
diff --git a/src/components/card/card.scss b/src/components/card/card.scss
index 9ec0e922ee9e..f99a69d1fe31 100644
--- a/src/components/card/card.scss
+++ b/src/components/card/card.scss
@@ -1,6 +1,6 @@
@import "variables";
-@import "shadows";
+@import "elevation";
@import "default-theme"; // TODO: Remove this
$md-card-default-padding: 24px !default;
@@ -9,18 +9,18 @@ $md-card-border-radius: 2px !default;
$md-card-header-size: 40px !default;
md-card {
+ @include md-elevation(1);
+ @include md-elevation-transition;
display: block;
position: relative;
padding: $md-card-default-padding;
border-radius: $md-card-border-radius;
- box-shadow: $md-shadow-bottom-z-1;
font-family: $md-font-family;
background: md-color($md-background, card);
}
md-card:hover {
- box-shadow: $md-shadow-bottom-z-2;
- transition: $swift-ease-in;
+ @include md-elevation(2);
}
.md-card-flat {
@@ -30,7 +30,7 @@ md-card:hover {
// base styles for each card section preset (md-card-content, etc)
%md-card-section-base {
display: block;
- margin-bottom: 16px;
+ margin-bottom: 16px;
}
md-card-title {
@@ -76,7 +76,7 @@ md-card-footer {
md-card-actions {
[md-button], [md-raised-button] {
margin: 0 4px;
- }
+ }
}
/* HEADER STYLES */
@@ -175,7 +175,7 @@ md-card-title-group {
margin-bottom: 0;
}
-// if main image is on top, need to place it flush against top
+// if main image is on top, need to place it flush against top
// (by stripping card's default 24px padding)
[md-card-image]:first-child {
margin-top: -24px;
@@ -208,7 +208,7 @@ md-card-header md-card-subtitle:not(:first-child) {
margin-top: -8px;
}
-// xl image should always have 16px on top.
+// xl image should always have 16px on top.
// when it's the first el, it'll need to remove 8px from default card padding of 24px
.md-card > [md-card-xl-image]:first-child{
margin-top: -8px;
diff --git a/src/components/sidenav/sidenav.scss b/src/components/sidenav/sidenav.scss
index 2dbf1c8890f9..42843ae2f3a5 100644
--- a/src/components/sidenav/sidenav.scss
+++ b/src/components/sidenav/sidenav.scss
@@ -1,7 +1,7 @@
@import "default-theme";
@import "mixins";
@import "variables";
-@import "shadows";
+@import "elevation";
// We use invert() here to have the darken the background color expected to be used. If the
@@ -31,14 +31,14 @@ $md-sidenav-push-background-color: md-color($md-background, dialog) !default;
will-change: transform;
}
&.md-sidenav-opening {
+ @include md-elevation(1);
visibility: visible;
transform: translateX($open);
will-change: transform;
- box-shadow: $md-shadow-bottom-z-1;
}
&.md-sidenav-opened {
+ @include md-elevation(1);
transform: translateX($open);
- box-shadow: $md-shadow-bottom-z-1;
}
}
diff --git a/src/core/style/_elevation.scss b/src/core/style/_elevation.scss
new file mode 100644
index 000000000000..728064ecaf8a
--- /dev/null
+++ b/src/core/style/_elevation.scss
@@ -0,0 +1,179 @@
+/**
+ * A collection of mixins and CSS classes that can be used to apply elevation to a material
+ * element.
+ * See: https://www.google.com/design/spec/what-is-material/elevation-shadows.html
+ * Examples:
+ *
+ *
+ * .md-foo {
+ * @include $md-elevation(2);
+ *
+ * &:active {
+ * @include $md-elevation(8);
+ * }
+ * }
+ *
+ *
+ *
+ * For an explanation of the design behind how elevation is implemented, see the design doc at
+ * https://goo.gl/Kq0k9Z.
+ */
+
+// Colors for umbra, penumbra, and ambient shadows. As described in the design doc, each elevation
+// level is created using a set of 3 shadow values, one for umbra (the shadow representing the
+// space completely obscured by an object relative to its light source), one for penumbra (the
+// space partially obscured by an object), and one for ambient (the space which contains the object
+// itself). For a further explanation of these terms and their meanings, see
+// https://en.wikipedia.org/wiki/Umbra,_penumbra_and_antumbra.
+
+$_umbra-color: rgba(black, 0.2);
+$_penumbra-color: rgba(black, 0.14);
+$_ambient-color: rgba(black, 0.12);
+
+// Maps for the different shadow sets and their values within each z-space. These values were
+// created by taking a few reference shadow sets created by Google's Designers and interpolating
+// all of the values between them.
+
+$_umbra-elevation-map: (
+ 0: '0px 0px 0px 0px #{$_umbra-color}',
+ 1: '0px 2px 1px -1px #{$_umbra-color}',
+ 2: '0px 3px 1px -2px #{$_umbra-color}',
+ 3: '0px 3px 3px -2px #{$_umbra-color}',
+ 4: '0px 2px 4px -1px #{$_umbra-color}',
+ 5: '0px 3px 5px -1px #{$_umbra-color}',
+ 6: '0px 3px 5px -1px #{$_umbra-color}',
+ 7: '0px 4px 5px -2px #{$_umbra-color}',
+ 8: '0px 5px 5px -3px #{$_umbra-color}',
+ 9: '0px 5px 6px -3px #{$_umbra-color}',
+ 10: '0px 6px 6px -3px #{$_umbra-color}',
+ 11: '0px 6px 7px -4px #{$_umbra-color}',
+ 12: '0px 7px 8px -4px #{$_umbra-color}',
+ 13: '0px 7px 8px -4px #{$_umbra-color}',
+ 14: '0px 7px 9px -4px #{$_umbra-color}',
+ 15: '0px 8px 9px -5px #{$_umbra-color}',
+ 16: '0px 8px 10px -5px #{$_umbra-color}',
+ 17: '0px 8px 11px -5px #{$_umbra-color}',
+ 18: '0px 9px 11px -5px #{$_umbra-color}',
+ 19: '0px 9px 12px -6px #{$_umbra-color}',
+ 20: '0px 10px 13px -6px #{$_umbra-color}',
+ 21: '0px 10px 13px -6px #{$_umbra-color}',
+ 22: '0px 10px 14px -6px #{$_umbra-color}',
+ 23: '0px 11px 14px -7px #{$_umbra-color}',
+ 24: '0px 11px 15px -7px #{$_umbra-color}'
+);
+
+$_penumbra-elevation-map: (
+ 0: '0px 0px 0px 0px #{$_penumbra-color}',
+ 1: '0px 1px 1px 0px #{$_penumbra-color}',
+ 2: '0px 2px 2px 0px #{$_penumbra-color}',
+ 3: '0px 3px 4px 0px #{$_penumbra-color}',
+ 4: '0px 4px 5px 0px #{$_penumbra-color}',
+ 5: '0px 5px 8px 0px #{$_penumbra-color}',
+ 6: '0px 6px 10px 0px #{$_penumbra-color}',
+ 7: '0px 7px 10px 1px #{$_penumbra-color}',
+ 8: '0px 8px 10px 1px #{$_penumbra-color}',
+ 9: '0px 9px 12px 1px #{$_penumbra-color}',
+ 10: '0px 10px 14px 1px #{$_penumbra-color}',
+ 11: '0px 11px 15px 1px #{$_penumbra-color}',
+ 12: '0px 12px 17px 2px #{$_penumbra-color}',
+ 13: '0px 13px 19px 2px #{$_penumbra-color}',
+ 14: '0px 14px 21px 2px #{$_penumbra-color}',
+ 15: '0px 15px 22px 2px #{$_penumbra-color}',
+ 16: '0px 16px 24px 2px #{$_penumbra-color}',
+ 17: '0px 17px 26px 2px #{$_penumbra-color}',
+ 18: '0px 18px 28px 2px #{$_penumbra-color}',
+ 19: '0px 19px 29px 2px #{$_penumbra-color}',
+ 20: '0px 20px 31px 3px #{$_penumbra-color}',
+ 21: '0px 21px 33px 3px #{$_penumbra-color}',
+ 22: '0px 22px 35px 3px #{$_penumbra-color}',
+ 23: '0px 23px 36px 3px #{$_penumbra-color}',
+ 24: '0px 24px 38px 3px #{$_penumbra-color}'
+);
+
+$_ambient-elevation-map: (
+ 0: '0px 0px 0px 0px #{$_ambient-color}',
+ 1: '0px 1px 3px 0px #{$_ambient-color}',
+ 2: '0px 1px 5px 0px #{$_ambient-color}',
+ 3: '0px 1px 8px 0px #{$_ambient-color}',
+ 4: '0px 1px 10px 0px #{$_ambient-color}',
+ 5: '0px 1px 14px 0px #{$_ambient-color}',
+ 6: '0px 1px 18px 0px #{$_ambient-color}',
+ 7: '0px 2px 16px 1px #{$_ambient-color}',
+ 8: '0px 3px 14px 2px #{$_ambient-color}',
+ 9: '0px 3px 16px 2px #{$_ambient-color}',
+ 10: '0px 4px 18px 3px #{$_ambient-color}',
+ 11: '0px 4px 20px 3px #{$_ambient-color}',
+ 12: '0px 5px 22px 4px #{$_ambient-color}',
+ 13: '0px 5px 24px 4px #{$_ambient-color}',
+ 14: '0px 5px 26px 4px #{$_ambient-color}',
+ 15: '0px 6px 28px 5px #{$_ambient-color}',
+ 16: '0px 6px 30px 5px #{$_ambient-color}',
+ 17: '0px 6px 32px 5px #{$_ambient-color}',
+ 18: '0px 7px 34px 6px #{$_ambient-color}',
+ 19: '0px 7px 36px 6px #{$_ambient-color}',
+ 20: '0px 8px 38px 7px #{$_ambient-color}',
+ 21: '0px 8px 40px 7px #{$_ambient-color}',
+ 22: '0px 8px 42px 7px #{$_ambient-color}',
+ 23: '0px 9px 44px 8px #{$_ambient-color}',
+ 24: '0px 9px 46px 8px #{$_ambient-color}'
+);
+
+/**
+ * The css property used for elevation. In most cases this should not be changed. It is exposed
+ * as a variable for abstraction / easy use when needing to reference the property directly, for
+ * example in a will-change rule.
+ */
+$md-elevation-property: box-shadow !default;
+
+/** The default duration value for elevation transitions. */
+$md-elevation-transition-duration: 280ms !default;
+
+/** The default easing value for elevation transitions. */
+$md-elevation-transition-timing-function: $md-fast-out-slow-in-timing-function;
+
+/**
+ * Applies the correct css rules to an element to give it the elevation specified by $zValue.
+ * The $zValue must be between 0 and 24.
+ */
+@mixin md-elevation($zValue) {
+ @if type-of($zValue) != number or not unitless($zValue) {
+ @error "$zValue must be a unitless number";
+ }
+ @if $zValue < 0 or $zValue > 24 {
+ @error "$zValue must be between 0 and 24";
+ }
+
+ #{$md-elevation-property}: #{map-get($_umbra-elevation-map, $zValue)},
+ #{map-get($_penumbra-elevation-map, $zValue)},
+ #{map-get($_ambient-elevation-map, $zValue)};
+}
+
+/**
+ * Returns a string that can be used as the value for a transition property for elevation.
+ * Calling this function directly is useful in situations where a component needs to transition
+ * more than one property.
+ *
+ * .foo {
+ * transition: md-elevation-transition-property-value(), opacity 100ms ease;
+ * will-change: $md-elevation-property, opacity;
+ * }
+ */
+@function md-elevation-transition-property-value(
+ $duration: $md-elevation-transition-duration,
+ $easing: $md-elevation-transition-timing-function) {
+ @return #{$md-elevation-property} #{$duration} #{$easing};
+}
+
+/**
+ * Applies the correct css rules needed to have an element transition between elevations.
+ * This mixin should be applied to elements whose elevation values will change depending on their
+ * context (e.g. when active or disabled).
+ */
+// NOTE(traviskaufman): Both this mixin and the above function use default parameters so they can
+// be used in the same way by clients.
+@mixin md-elevation-transition(
+ $duration: $md-elevation-transition-duration,
+ $easing: $md-elevation-transition-timing-function) {
+ transition: md-elevation-transition-property-value($duration, $easing);
+ will-change: $md-elevation-property;
+}
diff --git a/src/core/style/_shadows.scss b/src/core/style/_shadows.scss
deleted file mode 100644
index 7500a8170b01..000000000000
--- a/src/core/style/_shadows.scss
+++ /dev/null
@@ -1,5 +0,0 @@
-// Elements can have an "elevation" from 1 to 5, signified by shadows.
-// See http://google.com/design/spec/what-is-material/objects-in-3d-space.html
-
-$md-shadow-bottom-z-1: 0 2px 5px 0 rgba(0, 0, 0, 0.26) !default;
-$md-shadow-bottom-z-2: 0 4px 8px 0 rgba(0, 0, 0, 0.4) !default;
diff --git a/src/core/style/core.scss b/src/core/style/core.scss
new file mode 100644
index 000000000000..1725802f542e
--- /dev/null
+++ b/src/core/style/core.scss
@@ -0,0 +1,12 @@
+// Core styles that can be used to apply material design treatments to any element.
+
+@import 'elevation';
+
+// Provides external CSS classes for each elevation value. Each CSS class is formatted as
+// `md-elevation-z$zValue` where `$zValue` corresponds to the z-space to which the element is
+// elevated.
+@for $zValue from 0 through 24 {
+ .md-elevation-z#{$zValue} {
+ @include md-elevation($zValue);
+ }
+}