<div class="loading">
  <div class="inner"><p class="ellipsis"></p></div> 
</div>

<div class="item">
  <div class="inner"><p><p></div>
  <div class="border"></div>
  <div class="border"></div>
  <div class="border"></div>
  <div class="border"></div>
</div> 

<div class="item">
  <div class="inner"><p><p></div>
  <div class="border"></div>
  <div class="border"></div>
  <div class="border"></div>
  <div class="border"></div>
</div>

<div class="item">
  <div class="inner"><p><p></div>
  <div class="border"></div>
  <div class="border"></div>
  <div class="border"></div>
  <div class="border"></div>
</div> 

<div class="item">
  <div class="inner"><p><p></div>
  <div class="border"></div>
  <div class="border"></div>
  <div class="border"></div>
  <div class="border"></div>
</div>

<div class="item">
  <div class="inner"><p><p></div>
  <div class="border"></div>
  <div class="border"></div>
  <div class="border"></div>
  <div class="border"></div>
</div>
/* If you use any of this, it'd be nice to mention my name.

Andrew Tunnecliffe - 2014

*/

body, html {
  height:100%;
  width:100%;
  margin:0;
  transition:all 1s ease-in-out; 
}

p {
  font-family: 'Roboto', sans-serif;
}

/* Colours are `400` or `500` from Google's Material Design guidelines */

/* So at the start everything was just a floated inline block element, but when I wanted to animate them shrinking this became impossible. So everything is now an absolute child of the body element. */

/* Location and size of base units */
.loading {
  position:absolute;
  height:100%;
  width:100%;
  background:#26A69A;
  z-index:11;
  animation:fadeout 0.5s forwards 1s;
}
.item {
  float:left;
  overflow:hidden;
  position:absolute;
}
.inner {
  margin: auto;
  height:90%;
  width:90%;
  cursor:pointer;
  position: absolute;
  top: 0; left: 0; bottom: 0; right: 0;
  opacity:0;
  animation:fadein 0.5s forwards 2s;
}
.loading > .inner {
  opacity:1;
}
.loading > .inner > .ellipsis::after{
   content: '.';
   font-size: 1em;
   color: transparent;
   animation: ellipsis .75s steps(3) 5;
}
.inner p {
  font-size:xx-large;
  position:absolute;
  margin:0; 
  top: 50%;
  width:100%;
  text-align:center;
}
.border { 
  background:#333;
  position:absolute;
  transition:all 0.2s ease;
}

/* Items */
.item:nth-child(2) {
  z-index:10;
  background:#26A69A;
  width:100%;
  height:100%;
  animation: slidein1 0.4s forwards 1.2s;
}
.item:nth-child(3){
  z-index:9;
  background:#EC407A;
  right:0;
  width:50%;
  height:100%;
  animation: slidein2 0.4s forwards 1.4s;
}
.item:nth-child(4){
  z-index:8;
  left:50%;
  bottom:0;
  background:#AB47BC;
  width:50%;
  height:50%;
  animation: slidein3 0.4s forwards 1.6s;
}
.item:nth-child(5){
  z-index:7;
  right:0;
  top:50%;
  background:#5C6BC0;
  width:25%;
  height:50%;
  animation: slidein4 0.4s forwards 1.8s;
}
.item:nth-child(6){
  z-index:6; 
  left:75%;
  bottom:0;
  background:#26C6DA;
  width:25%;
  height:25%;
}

/* Animations */
/* "Authentic Motion" */
@keyframes slidein1 {
  0% {width:100%;}
  100% {width:50%;}
}
@keyframes slidein2 {
  0% {height:100%;}
  100% {height:50%;}
}
@keyframes slidein3 {
  0% {width:50%;}
  100% {width:25%;}
}
@keyframes slidein4 {
  0% {height:50%;}
  100% {height:25%;}
}
@keyframes slidein5 {
  0% {width:25%;}
  100% {width:12.5%;}
}
@keyframes fadeout {
  0% {opacity:1;background:#26A69A;}
  50% {background:#4DB6AC;} /* Fade lighter: #00897B */
  99% {height:100%;width:100%;opacity:0;}
  100% {height:0;width:0;opacity:0;} 
}
@keyframes fadein {
  0% {opacity:0;}
  100% {opacity:1;}
}
@keyframes ellipsis {
    0%   {color: transparent; text-shadow: none;}
    1%   {color: #333; text-shadow: .5em 0 0 transparent, 1em 0 0 transparent;}
    26%  {color: black; text-shadow: .5em 0 0 transparent, 1em 0 0 transparent;}
    51%  {color: black; text-shadow: .5em 0 0 black, 1em 0 0 transparent;}
    76%  {color: black; text-shadow: .5em 0 0 black, 1em 0 0 black;}
    100% {color: black; text-shadow: .5em 0 0 black, 1em 0 0 black;}
}

/* Borders */
.item > .border:nth-child(2) {
  width:20px;
  height:100%;
  left:-20px;
}
.item > .border:nth-child(3) {
  width:20px;
  height:100%;
  right:-20px;
}
.item > .border:nth-child(4) {
  width:100%;
  height:20px;
  top:-20px;
}
.item > .border:nth-child(5) {
  width:100%;
  height:20px;
  bottom:-20px;
}

/* Border Animation */
.item:hover > .border:nth-child(2){
  left:0;
}
.item:hover > .border:nth-child(3) {
  right:0;
}
.item:hover > .border:nth-child(4) {
  top:0;
}
.item:hover > .border:nth-child(5) {
  bottom:0;
}

/* Added Material Button */
.circle {
  display: block;
  position: absolute;
  background: rgba(0, 0, 0, 0.075);
  border-radius: 50%;
  -webkit-transform: scale(0);
      -ms-transform: scale(0);
          transform: scale(0);
}
.circle.animate {
  -webkit-animation: effect 0.65s linear;
          animation: effect 0.65s linear;
}

@-webkit-keyframes effect {
  100% {
    opacity: 0;
    -webkit-transform: scale(2.5);
            transform: scale(2.5);
  }
}

@keyframes effect {
  100% {
    opacity: 0;
    -webkit-transform: scale(2.5);
            transform: scale(2.5);
  }
}
/* If you use any of this, it'd be nice to mention my name.

Andrew Tunnecliffe - 2014

JS is only for the circles, not for the loading or hover animations.
*/

// Basic queue / FILO implementation. 

var element, circle, d, x, y;
var i = 1;
var queue = [];

$(".inner").click(function(e){
  element = $(this);
  
  // remove old items from queue and DOM
  // allow max 5 to be loaded
  if (queue.length > 5) {
    $("._" + queue.shift()).remove();
  }
  
  // Assume user can't click more than 1000 times / second
  //terrible overflow protection.
  if (i > 1000) {
    i = 0;
  }
  
  // add next item to queue
  i++;
  queue.push(i);
  
  // Build element
  element.append("<span class='circle _" + i + "'></span>");
  circle = element.find("._" + i);
	
  // Make it big enough to cover whole parent
  if(!circle.height() && !circle.width()) {
    d = Math.max(element.outerWidth(), element.outerHeight());
    circle.css({height: d, width: d});
  }
	
  // Get origin
  x = e.pageX - element.offset().left - circle.width() / 2;
  y = e.pageY - element.offset().top - circle.height() / 2 ;
	
  // Set location and animate
  circle.css({top: y+'px', left: x+'px'}).addClass("animate");
})

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. //cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js