Material Shadows Mixin

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;
}

See the Pen Material shadow by Hugo Giraudel (@HugoGiraudel) on CodePen.

Comments

  1. User Avatar
    Ben
    Permalink to comment#

    So how do i use it for Div’s instead of li’s? just started learning this stuff.. i can get it to style the li’s in the div.

    • User Avatar
      Ben
      Permalink to comment#

      Ah its ok. i just added @include card(5); to the class.

      Really like it. thanks

  2. User Avatar
    lukefrake
    Permalink to comment#

    Really like this! I would do:

    @mixin card($depth:1) {

    To promote the use of keeping your shadow depth low where possible :)

  3. User Avatar
    Ezra

    Awesome! This is really helpful and powerful little mixin, thank you.

  4. User Avatar
    Neila

    WOO! AMAZING HOLY COW! Just what I wanted :)

  5. User Avatar
    pht
    Permalink to comment#

    Silly question, but where do the “magic numbers” (for offset, blur level, colors, etc…) come from ?
    Also, shouldn’t one of the shadow have a negative inset ?

    Thanks

  6. User Avatar
    Satyajit Sahoo
    Permalink to comment#

    The opacity needs to be half, otherwise it looks too dark.

  7. User Avatar
    BT
    Permalink to comment#

    Can you please make your website wider than an index card? People aren’t reading your blog of a TI-89

  8. User Avatar
    Remy Sheppard
    Permalink to comment#

    This is exactly what I needed for a project I’m working on.

    I threw together a quick CodePen for you where I apply your mixin to a z-n class so that the shadows can be applied quickly through HTML, vis-a-vis:

    <div class="z-2 myBox">

    You can find it here

Submit a Comment

Posting Code

You may write comments in Markdown. This makes code easy to post, as you can write inline code like `<div>this</div>` or multiline blocks of code in triple backtick fences (```) with double new lines before and after.

Code of Conduct

Absolutely anyone is welcome to submit a comment here. But not all comments will be posted. Think of it like writing a letter to the editor. All submitted comments will be read, but not all published. Published comments will be on-topic, helpful, and further the discussion or debate.

Want to tell us something privately?

Feel free to use our contact form. That's a great place to let us know about typos or anything off-topic.

icon-anchoricon-closeicon-emailicon-linkicon-logo-staricon-menuicon-nav-guideicon-searchicon-staricon-tag