<h1>Ripple effect using CSS Variables</h1>
<span>
<button anim="ripple">Button</button>
<a href="#" anim="ripple">Link</a>
<a class="rainbow" href="#" anim="ripple">Rainbow</a>
[anim="ripple"] {
    
    //  Customize effect by defining the following
    //  variables on the parent element 
    //  --ripple-background: white;
    //  --ripple-opacity: 0.3;  
    //  --ripple-duration: 600ms;      
    //  --ripple-easing: linear;
    
    position: relative;
    overflow: hidden;

    &:before {
        content: '';
        position:absolute;
        display: block;
        background: var(--ripple-background, white);      
        border-radius: 50%;
        pointer-events: none; 
        
        //  position and size 
        top: calc(var(--y) * 1px);
        left: calc(var(--x) * 1px);
        width:  calc(var(--d) * 1px);
        height: calc(var(--d) * 1px);

        //  animated properties
        opacity: calc(var(--o, 1) * var(--ripple-opacity, 0.3));                
        transition: calc(var(--t, 0) * var(--ripple-duration, 600ms)) var(--ripple-easing,linear);   
        transform: translate(-50%, -50%) scale(var(--s, 1));
        transform-origin: center;
    }
}









//  Just some styling 
button {
    
    --ripple-background: white;
    --ripple-opacity: 0.3;  
    --ripple-duration: 600ms;      
    
    border:1px solid darken(tomato, 20%);
    border-radius:0;
    padding: 0.75em 3em;
    font-size: 1em;
    outline: none;
    display:block;
    background: tomato;
    color: white;
    -webkit-tap-highlight-color: rgba(0,0,0,0);
    min-width: 200px;
    text-align: center; 
    cursor: pointer;
    user-select: none;
}
a {
    
    --ripple-background: black;    
    --ripple-opacity: 0.1;    
    --ripple-duration: 600ms;    
    
    display: block;
    margin-top: 1em;
    padding: 0.75em 3em;
    background: whitesmoke; 
    color: black;
    text-decoration: none;
    border:1px solid darken(whitesmoke, 10%);    
    min-width: 200px;
    text-align: center; 
    -webkit-tap-highlight-color: rgba(0,0,0,0);    
    
    transition: background-color 300ms;
    &:hover { background-color: darken(whitesmoke, 3%);}    
}

.rainbow {
    --ripple-opacity: 1;
    --ripple-background: radial-gradient(circle at center, rebeccapurple, dodgerblue, olive, gold, orange, tomato);
    --ripple-duration: 2000ms;
    --ripple-easing: cubic-bezier(0, .5, .5, 1);    
    background-color: skyblue;
    color: rgba(white, 0.7);

    transition: background-color 300ms, color 300ms;
    &:hover { background-color: darken(skyblue, 10%); color: rgba(white, 1);}
}



@import url("https://fonts.googleapis.com/css?family=Roboto:400,400i,700");
html { box-sizing: border-box; } *,*::before,*::after { box-sizing: inherit; }
html, body { height: 100%; font-family: Roboto, sans-serif}
body { margin: 0; display: flex; flex-direction: column; justify-content: center; align-items: center; }
h1 { font-size:1.2em;}
View Compiled
[].map.call(document.querySelectorAll('[anim="ripple"]'), el=> {
    el.addEventListener('click',e => {
        e = e.touches ? e.touches[0] : e;
        const r = el.getBoundingClientRect(), d = Math.sqrt(Math.pow(r.width,2)+Math.pow(r.height,2)) * 2;
        el.style.cssText = `--s: 0; --o: 1;`;  el.offsetTop; 
        el.style.cssText = `--t: 1; --o: 0; --d: ${d}; --x:${e.clientX - r.left}; --y:${e.clientY - r.top};`
    })
})



View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.