#app
	ti-ripple-button(text="I'm a ripple button")
View Compiled
@import url("https://fonts.googleapis.com/css?family=Inconsolata:400,700");

$black: #000;
$white: #fff;
$shocking-pink: #ff1ead;

html, body {
	width: 100%;
	height: 100%;
}

body {
	font-family: Inconsolata, monospace;
	font-size: 24px;
	background-color: $black;
	display: grid;
	place-items: center;
}

.ti-btn {
	color: $white;
	font: inherit;
	background-color: $black;
	border: solid 4px $white;
	padding: 20px 30px;
	outline: 0;
	overflow: hidden;
	display: inline-block;
	position: relative;
	user-select: none;
	box-shadow: 0 0 0 0 rgba($white, 0.5);
	transition: box-shadow 150ms ease-out;
	&:focus {
		box-shadow: 0 0 0 8px rgba($white, 0.5);
	}
}

.ripple {
	background-color: $shocking-pink;
	width: 1rem;
	height: 1rem;
	position: absolute;
	border-radius: 50%;
	transform: translateX(-100%) translateY(-100%);
	mix-blend-mode: screen;
	animation: ripple 1250ms ease-out forwards, fade 1500ms ease-out forwards;
}

@keyframes ripple {
	0%   { transform: translate(-100%, -100%); }
	80%  { transform: translate(-100%, -100%) scale(50); }
	100% { transform: translate(-100%, -100%) scale(50); opacity: 0; }
}

@keyframes fade {
	0%   { opacity: 1; }
	100% { opacity: 0; }
}
View Compiled
Vue.component('ti-ripple-button', {
	props: ['text'],
	data: function() {
		return {
			ripples: []
		}
	},
	methods: {
		animateRipple: function(e) {
			let el  = this.$refs.tiBtn;
			let pos = el.getBoundingClientRect();
			
			this.ripples.push({
				x: e.clientX - pos.left,
				y: e.clientY - pos.top,
				show: true
			});
		},
		rippleEnd: function(i) {
			this.ripples[i].show = false;
		}
	},
	template: `
<button class="ti-btn" ref="tiBtn" v-on:click="animateRipple">
	{{text}}
	<transition-group>
		<span
			class="ripple"
			v-bind:ref="'ripple-' + i"
			v-bind:key="'ripple' + i"
			v-for="(val, i) in ripples"
			v-if="val.show === true"
			v-bind:style="{'top': val.y + 'px', 'left': val.x + 'px'}"
			v-on:animationend="rippleEnd(i)">
		</span>
	</transition-group>
</button>
`
});

var app = new Vue({
	el: '#app'
});
View Compiled

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js