Material Shadows Mixin

Avatar of Kitty Giraudel
Kitty Giraudel on (Updated on )

Material Design has been all over the place lately. One part of it consists on stacking layers on top of each others like real paper sheets. To achieve such an effect in CSS, we need to use the box-shadow property.

To avoid having to manually write the shadows every time, we can build a little Sass mixin for it. The only thing this mixin will do is outputting a box-shadow declaration based on the given $depth (from 0 to 5). Shadows will actually be computed by two functions: bottom-shadow and top-shadow.

/// Gives a card depth effect.
/// @param {Number} $depth - depth level (between 1 and 5)
/// @link http://www.google.com/design/spec/layout/layout-principles.html#layout-principles-dimensionality Google Design
/// @requires {function} top-shadow
/// @requires {function} bottom-shadow
@mixin card($depth) {
  @if $depth < 1 {
    box-shadow: none;
  } @else if $depth > 5 {
    @warn "Invalid $depth `#{$depth}` for mixin `card`.";
  } @else {
    box-shadow: bottom-shadow($depth), top-shadow($depth);  
  }
}

Let’s not forget our two functions:

/// Computes a top-shadow for a card effect.
/// @param {Number} $depth - depth level
/// @return {List}
@function top-shadow($depth) {
  $primary-offset: nth(1.5 3 10 14 19, $depth) * 1px;
  $blur: nth(1.5 3 10 14 19, $depth) * 4px;
  $color: rgba(black, nth(.12 .16 .19 .25 .30, $depth));

  @return 0 $primary-offset $blur $color;
}

/// Computes a bottom-shadow for a card effect.
/// @param {Number} $depth - depth level
/// @return {List}
@function bottom-shadow($depth) {
  $primary-offset: nth(1.5 3 6 10 15, $depth) * 1px;
  $blur: nth(1 3 3 5 6, $depth) * 4px;
  $color: rgba(black, nth(.24 .23 .23 .22 .22, $depth));

  @return 0 $primary-offset $blur $color;
}