Dynamic Scrolling Shadow

Alt Text

Scrolling Shadow Effect

I stumbled across the VoicesHavePower website which uses a nice grid layout to separate its contents. It showcases stories each with a content panel that gives off a nice looking flat shadow. As you scroll through the website, each individual panel dynamically shifts the shadow based on where it is in your window. I’ve recreated this effect with CSS3 transform effects and some jQuery.

HTML Structure

This is the basic structure for the content panel. The Grid-Container is what contains the colored background, panel and shadow. The Shadow-Box is actually what has the scrolling shadow effect.

<div class="grid-container blue">
  <div class="shadow-box">
    <div class="content">
    </div>
    <div class="shadows">
      <div class="shadow top"></div>
      <div class="shadow bottom"></div>
    </div>
  </div>
</div>

Scrolling Shadow Styles

Here is the css for the shadow box. The scrolling shadow effect is created with 2 shadow elements, one positioned to the top right corner of the content box, and the other positioned at the bottom left corner. Together they are animated and they are bounded by the grid-container class.

.shadow-box {
display: block;
position: relative;
z-index: 1;
width: 300px;
height: 400px;
}
.shadow-box .content {
  position: relative;
  z-index: 1;
  width: inherit;
  height: inherit;
  background-color: #fff;
}

.shadow-box .shadows {
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";
  filter: alpha(opacity=30);
  -moz-opacity: 0.3;
  -khtml-opacity: 0.3;
  opacity: 0.3;
}
  .shadow-box .shadow {
    position: absolute;
    z-index: -1;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 200%;
    background-color: #444;

    -webkit-transform: rotate(-45deg);
    -moz-transform: rotate(-45deg);
    -ms-transform: rotate(-45deg); 
    -o-transform: rotate(-45deg);
    transform: rotate(-45deg);
  }
  .shadow-box .shadow.top {
    right: 0;
    top: 0;
    -webkit-transform-origin: 100% 0;
    transform-origin: 100% 0;
  }
  .shadow-box .shadow.bottom {
    -webkit-transform-origin: 0 0;
    transform-origin: 0 0;
    right: 0;
    top: 100%;
  }

jQuery

This is where the scrolling shadow angle is calculated. Basically, for each shadow-box it will calculate a percentage for how far scrolled it is within the current view of the window. You can change how angled the shadow starts out as and where it will end once you’ve completely scrolled past it, by altering the startingRotate and endingRotate variables.

// scrolling shadow effect
function updateParallax() {
  $(".grid-container").each(function () {

    var height = $(this).height();
    var bottom = $(this).offset().top + height;
    var top = $(this).offset().top;
    var windowHeight = $(window).height();
    var scrollTop = $(window).scrollTop() + windowHeight;
    var fromTop = $(window).scrollTop() - top; 

    if ((bottom > $(window).scrollTop()) && (top < scrollTop)) {             
      var percent = ((scrollTop - top) / (height + windowHeight));
      var startingRotate = -80; // Starting angle of shadow
      var endingRotate = -15; // Ending angle of shadow
      var shadowRotate =  (startingRotate - endingRotate) * (1 - percent) + endingRotate;
      if (shadowRotate < startingRotate) {
        shadowRotate = startingRotate
      }
      else if (shadowRotate > 0) {
        shadowRotate = 0;
      }
      $(this).find('.shadow-box .shadow').css({'-webkit-transform': 'rotate(' + shadowRotate + 'deg)' });
      $(this).find('.shadow-box .shadow').css({'-moz-transform': 'rotate(' + shadowRotate + 'deg)' });
      $(this).find('.shadow-box .shadow').css({'-ms-transform': 'rotate(' + shadowRotate + 'deg)' });
      $(this).find('.shadow-box .shadow').css({'-o-transform': 'rotate(' + shadowRotate + 'deg)' });
      $(this).find('.shadow-box .shadow').css({'transform': 'rotate(' + shadowRotate + 'deg)' });
    }

  });
}
updateParallax();

$(window).scroll(function() {
  updateParallax();
});