<script>
console.clear();
const EVENT = 'mousedown';
function removeRipple(event) {
const ripple = this;
ripple.remove();
ripple.addEventListener('animationend', removeRipple);
}
function createRipple(event) {
const target = event.currentTarget;
const { top, left } = target.getBoundingClientRect();
const { clientWidth, clientHeight } = target;
const diameter = Math.sqrt(clientWidth ** 2 + clientHeight ** 2);
const radius = diameter / 2;
const localX = event.clientX - left;
const localY = event.clientY - top;
const ripple = document.createElement('span');
ripple.setAttribute('class', 'v-ripple');
ripple.setAttribute(
'style',
`
width: ${diameter}px;
height: ${diameter}px;
left: ${localX - radius}px;
top: ${localY - radius}px;
`,
);
ripple.addEventListener('animationend', removeRipple);
target.appendChild(ripple);
}
const ripple = {
mounted(el) {
el.addEventListener(EVENT, createRipple);
},
unmounted(el) {
el.removeEventListener(EVENT, createRipple);
},
};
export default {
directives: { ripple },
};
</script>
<template>
<div class="container">
<button v-ripple type="button" class="button">BUTTON</button>
<button v-ripple type="button" class="button is-outline">BUTTON</button>
<button v-ripple type="button" class="button button-primary">BUTTON</button>
<button v-ripple type="button" class="button button-primary is-outline">BUTTON</button>
</div>
</template>
<style>
/* reboot */
*, *::after, *::before {
box-sizing: border-box;
}
#app {
display: flex;
justify-content: center;
align-items: center;
padding: 5px;
height: 100vh;
overflow: hidden;
font-family: "Roboto", sans-serif;
}
button {
margin: 0;
padding: 0;
outline: none;
border: none;
background: transparent;
font-family: inherit;
}
/* layout */
.container {
min-width: 320px;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
/* button */
.button {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.5rem 1rem;
overflow: hidden;
font-size: 1rem;
color: #6B7280;
cursor: pointer;
background-color: #eee;
border-radius: 0.25rem;
border: 1px solid transparent;
box-shadow: 1px 2px 1px -1px rgba(0, 0, 0, 0.2);
}
.button:active {
box-shadow: inset 1px 1px 2px 0 rgba(0, 0, 0, 0.2);
}
.button-primary {
color: #eee;
background: #3B82F6;
}
.button.is-outline {
background: transparent;
border: 1px solid #6B7280;
}
.button-primary.is-outline {
border-color: #3B82F6;
color: #3B82F6;
}
/* ripple effect */
.v-ripple {
position: absolute;
background-color: currentColor;
border-radius: 50%;
opacity: 0.2;
transform: scale(0);
animation: v-ripple-animation 0.6s linear;
}
@keyframes v-ripple-animation {
to {
opacity: 0;
transform: scale(4);
}
}
</style>
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.