Work

Work

Snippets

Snippets

Graphics

Graphics

Blog

Blog

Email Search

Shadow Cast

By Dónal - December 2016

JavaScript

Mouse control

Mouse-controlled CSS shadows.

View Demo

Using the mouse to dynamically control elements on screen can be fun to experiment with and yield interesting effects. Javascript allows for the tracking of mouse pointer coordinates, which can be monitored in real time and applied to control an effect. In this simple example, I’m using these coordinates to control the direction and length of shadows (CSS box-shadow), creating the illusion of a light source that can cast shadows from on-screen elements . I’ll use a pyramid to demonstrate this as it contains basic HTML block elements and it’s 3D geometric shape aids the illusion of depth.

The markup is very basic – the pyramid consists of eight nested <div> blocks:

<div class="pyramid pyramid-base">
  <div class="pyramid">
    <div class="pyramid">
      <div class="pyramid">
        <div class="pyramid"> 
          <div class="pyramid"> 
            <div class="pyramid"> 
              <div class="pyramid">
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

The CSS sets the outer block in place and applies dimensions to each subsequent block as a percentage of its parent’s dimensions, centering each within it’s parent. The result is a nest of concentric squares of decreasing dimensions. The outer block is rotated slightly and repeated backgrounds are applied to its surfaces and the surrounding body to create the plan view of the pyramid in its desert-like landscape. The final touch of CSS is to initialize the shadows by applying the same box-shadow to each nested <div>.

body {
margin: 0;
background: #fff5cc;
background: url(http://klindenmeyer.com/wp-content/uploads/2013/02/Sand-Texture.jpg);
}
 
.pyramid {
position: absolute;
width: 86%;
height: 86%;
top: 7%;
left: 7%;
box-shadow: 0px 0px 20px 2px #333;
background: #ffeecc;
background: url(http://www.marshalls.co.uk/dam-svc/AssetStore/Saxon-Textured-Kerb--Natural-5961.jpg?MaxWidth=1920&MaxHeight=1080);
}
 
.pyramid-base {
position: absolute;
top: 50%;
left: 50%;
width: 360px;
height: 360px;
margin: -180px 0 0 -180px;
box-shadow: 0px 10px 20px 2px #333;
 
-webkit-transform: rotate(5deg);
-moz-transform: rotate(5deg);
transform: rotate(5deg);
}

As is so often the case, JavaScript (with the help of jQuery) will bring this to life. The idea here is that when the mouse hovers directly over the pyramid, the shadow will be at its minimum, much like the sun shining from directly overhead. The further the mouse moves away from the pyramid, the more shadow it casts. So first, let’s determine the centre of the pyramid by finding its offset location on the screen, its width and height, and then working out the centre:

// Get centre of pyramid
var pyramidBase = $('.pyramid-base');
var offset = pyramidBase.offset();
var width = pyramidBase.width();
var height = pyramidBase.height();
var centerX = offset.left + width / 2;
var centerY = offset.top + height / 2;

Now, let’s use the jQuery mousemove() method to track the mouse coordinates relative to the document:

// Get centre of pyramid
var pyramidBase = $('.pyramid-base');
var offset = pyramidBase.offset();
var width = pyramidBase.width();
var height = pyramidBase.height();
var centerX = offset.left + width / 2;
var centerY = offset.top + height / 2;
 
$(document).mousemove(function(event){
 
	// Get mouse coordinates
	var mouseX = event.pageX;
	var mouseY = event.pageY;
});

Using this method, we can create a dynamic variable based on the position of the mouse relative to the position of the centre of the pyramid. The number should equal 0 when directly above the pyramid and increase as the mouse moves away. To do this, we subtract the centre positions from the mouse positions (X and Y). This will yield a positive value when the mouse is on one side and a negative on the other. Before applying this to the CSS, a couple of adjustments need to be made. As it stands, the results will place the shadow on the same side as the mouse, so we need to reverse this by multiplying both coordinates  by -1. Secondly, the values are far too high to be applied to box-shadow pixels units – they would carry the shadow off the object of origin altogether. So to make it a more realistic result, I’m dividing both by a 10th of the pyramid’s width (this can be altered by in anyway really, depending on the desired outcome):

// Get centre of pyramid
var pyramidBase = $('.pyramid-base');
var offset = pyramidBase.offset();
var width = pyramidBase.width();
var height = pyramidBase.height();
var centerX = offset.left + width / 2;
var centerY = offset.top + height / 2;
 
$(document).mousemove(function(event){
 
	// Get mouse coordinates
	var mouseX = event.pageX;
	var mouseY = event.pageY;
 
	// Get distance from centre
	var distanceX = (mouseX - centerX) / (width/10);
	distanceX *= -1;
	var distanceY = (mouseY - centerY) / (width/10);
	distanceY *= -1;
 
	});
 
});

Finally, we apply the dynamic distances to the CSS box-shadow of the pyramid’s blocks by inserting the variables into the respective X and Y values:

// Get centre of pyramid
var pyramidBase = $('.pyramid-base');
var offset = pyramidBase.offset();
var width = pyramidBase.width();
var height = pyramidBase.height();
var centerX = offset.left + width / 2;
var centerY = offset.top + height / 2;
 
$(document).mousemove(function(event){
 
	// Get mouse coordinates
	var mouseX = event.pageX;
	var mouseY = event.pageY;
 
	// Get distance from centre
	var distanceX = (mouseX - centerX) / (width/10);
	distanceX *= -1;
	var distanceY = (mouseY - centerY) / (width/10);
	distanceY *= -1;
 
	$('.pyramid-block').each( function() {
		$(this).css('box-shadow', distanceX + 'px ' + distanceY + 'px 20px 0px #333');
	});
 
});

That’s it, try it out! Try changing the shadow distances and directions. Use the same method to cast shadows from your own HTML structure…

View Demo

Share on

Share on Facebook Share on Twitter Share on Google Plus Share on Pinterest

View more

CSS

Google

JavaScript

Lists

Mouse control

Multi-layered

Parallax

Scroll event

Visual feedback