/ Material Design

A couple of buttons to demonstrate Google's Material Design button ripple effect

A couple of buttons to demonstrate Google's Material Design button ripple effect

Google Button Ripple

A couple of buttons to demonstrate Google's Material Design button ripple effect when being clicked.

I'll probably be making this into a simple plugin for myself soon.

Update: Fixed the border-radius clip issue and made it closer to native buttons based from Polymer.

Made with

Html
Css
JavaScript

html

<h1>Google Material Design Buttons</h1>
<h2>A couple of buttons to demonstrate the ripple effect on Google's Material Design buttons.</h2>
<p>Google's docs for this are <a href="https://www.google.com/design/spec/animation/responsive-interaction.html" target="_blank">here</a>.</p>

<div class="container">
  <p>
<button type="button" class="button button-ripple">
  Text 
</button>
    &nbsp;
<button type="button" class="button button-ripple" data-ripple-color="yellow">
  Text 
</button>
  </p>
<p>
  <button type="button" class="button button-ripple button-round">
  !
</button> 
  &nbsp;
  <button type="button" class="button button-ripple button-round button-white">
  !
</button>
  </p>
</div>

Css

.button {
  background: orange;
  outline: none;
  color: white;
  border: none;
  border-radius: 0.25em;
  padding: 0.75em 2em;
  line-height: 1;
  box-shadow: 0 0 0.25em rgba(0,0,0,0.5);
  text-shadow: 0 0 0.25em rgba(0,0,0,0.5);
  font-size: 1.5rem;
}
.button-white {
  background: white;
  color: orange;
}
.button-round {
  border-radius: 100%;
  padding: 0.75em;
  width: 3em;
  height: 3em;
}
.button-ripple {
  position: relative;
  overflow: hidden;
  transform: translate(0);
}
.button-ripple_content {
  position: relative;
  z-index: 1;
}
.button-ripple_ripples {
  position: absolute;
  top: 0;
  left: 0;
}
.button-ripple_ripple{
  display: block;
  position: absolute;
  border-radius: 50%;
  width: 1em;
  height: 1em;
  margin: -0.5em 0 0 -0.5em;
  transform: scale(0);

  top: 0;
  left: 0;

  animation: ripple-animation 2s;
}

@keyframes ripple-animation {
    from {
      transform: scale3d(1,1,1);
      opacity: 0.8;
    }
    to {
      transform: scale3d(100,100,1);
      opacity: 0;
    }
}

/* Make things perty */
html {  height: 100%;}
body { font-family: 'Source Sans Pro', Helvetica, Arial, sans-serif; background-color: #0d0d0d; color: #fff; height: 100%; padding-top: 2em; text-align: center;}
h1, h2{ margin: 0; text-transform: uppercase;text-shadow: 0 0 0.5em black;}
h2 { font-weight: 300}
input { border: 1px solid #666; background: #333; color: #fff; padding: 0.5em; box-shadow: none; outline: none !important; margin: 1em  auto; text-align: center;}
a { color: orange; text-decoration: none; transition: color 250ms ease-in-out;}
a:hover { color: yellow;}
.container { display:block; margin: 2em 0;}

JavaScript

jQuery(document).ready(function(){
  
  ripple.init();
$('.button-ripple').on('click touchstart', ripple.click);
  
});

var ripple = {
  click: function(event){
  /*
  if ( $(this).find('.ripple').length ){
    return;
  }
  */
  event.preventDefault();
  
  var 
    $this = $(this),
    $ripples = $this.find('.button-ripple_ripples'),
    rippleColor = $this.attr('data-ripple-color') || $this.css('color'),
    btnOffset = $this.offset(),
    inputX = ( event.type === 'click' ) ? event.pageX : event.originalEvent.touches[0].pageX,
    inputY = ( event.type === 'click' ) ? event.pageY : event.originalEvent.touches[0].pageY,
    xPos = inputX - btnOffset.left,
    yPos = inputY - btnOffset.top;
  
    $ripples.append('<span class="button-ripple_ripple"></span>');
    
    var $ripple = $ripples.find('.button-ripple_ripple');
    
    $ripple.on(animationEnd, function(){ $(this).remove(); });
  
    $ripples[0].style.webkitTransform = 'translate3d(' + xPos + 'px,' + yPos + 'px,0)';
    $ripples[0].style.transform = 'translate3d(' + xPos + 'px,' + yPos + 'px,0)';
    
    $ripple.css({ backgroundColor: rippleColor });
    
},
  init: function(){
    $('.button-ripple').wrapInner('<span class="button-ripple_content"></span>');
    $('.button-ripple').append('<div class="button-ripple_ripples"></div>')
  }
};

var animation = {
	// Determines proper transition property per browser
	whichAnimationEvent: function(){
		var t;
		var el = document.createElement('fakeelement');
		var transitions = {
			'OAnimation':'oanimationend',
			'MozAnimation':'animationend',
			'WebkitAnimation':'webkitAnimationEnd',
			'animation':'animationend'
		};
		for(t in transitions){
			if( el.style[t] !== undefined ){
				return transitions[t];
			}
		}
	}
};
// Makes it easier to bind cross browser, like $('element').one(transitionEnd, function(){});
var animationEnd = animation.whichAnimationEvent(); 

Demo

See the Pen Google Button Ripple by Jon Christensen (@JMChristensen) on CodePen.