Lollipop click animation
Android 5.0 Lollipop brought us some fancy new design (material design). This trend is finding its way onto the web. So we, as webdevelopers, should find techniques to transpose these OS capabilities to the interwebz.
by BramVanroy
HTML
<script src="http://fonts.googleapis.com/css?family=Roboto:500,900italic,900,400italic,100,700italic,300,700,500italic,100italic,300italic,400"></script>
<div class="thumbnail"></div>
<div class="buttons">
<button class="bubble-wrap blue-light">Click me</button>
<button class="bubble-wrap yellow">Click me</button>
<button class="bubble-wrap pink">Click me</button>
<button class="bubble-wrap blue-dark">Click me</button>
</div>
<div id="description">
<h1>Lollipop click animations in CSS</h1>
<p>Android 5.0 Lollipop brought us some fancy new design (<em>material</em> design). This trend is finding its way onto the web. So we, as webdevelopers, should find techniques to transpose these OS capabilities to the interwebz.</p>
<p>I took the liberty to edit <a href="http://codepen.io/dwijitsolutions/pen/myrvJW" target="_blank">this pen</a> by dwijitsolutions. I used jQuery - 'cause <em>I'm lovin' it</em> - and added some improvements overall. Especially automatically determining the correct width for the bubble and its position, and fetching the correct timeOut before deleting the added elements are huge additions.</p>
<p>You could also apply this technoqie on links (<code><a></a></code>), but that would be quite useless for off-page navigation. In other words, when you click a link, the browser immediately redirects you so you won't see the animation anyway. The animation is ideally used for buttons that do an on-page action, e.g. ajax calls and form submits.</p>
</div>
SCSS
/* STYLE FOR THE ANIMATIONS
These styles are required
for the lollipop click effect
*/
.bubble-wrap {
width: 120px;
height: 50px;
border-radius: 6px;
position: relative;
text-align: center;
cursor: pointer;
overflow: hidden;
border: 0 none;
background: #F06292;
color: #FFF;
font: {
size: 16px;
weight: 900;
family: inherit;
};
line-height: 50px;
margin: 25px;
/* Fix webkit overflow problem */
z-index: 0;
&:focus {outline: none;}
}
.pink {background: #F06292;}
.yellow {background: #E2DC35;}
.blue-light {background: #80B5BF;}
.blue-dark {background: #1A6F84;}
.bubble {
position: absolute;
background: rgba(255, 255, 255, 0.36);
pointer-events: none;
border-radius: 50%;
opacity: 0;
transform: scale(0);
animation: bubble-effect-in 1s forwards, bubble-effect-out 1.6s 1s forwards;
}
@keyframes bubble-effect-in {
0% {
opacity: 0;
transform: scale(0);
}
100% {
opacity: 1;
transform: scale(1);
}
}
@keyframes bubble-effect-out {
from {opacity: 1;}
to {opacity: 0;}
}
/* STYLE FOR THIS FIDDLE
The styles below are merely for illustration, and
not required for the animation
*/
body {
font: 300 16px/1.4 Roboto,"Roboto",Helvetica,Arial,sans-serif;
max-width: 1280px;
min-width: 480px;
margin: 0 auto;
}
em {font-style: italic;}
bold {font-weight: 700;}
h1 {
font: {
size: 36px;
weight: 100;
};
text-align: center;
border-bottom: 1px solid;
}
p {margin: 1.2em 0;}
a {
color: inherit;
text-decoration: underline;
&:hover {text-decoration: none;}
}
code {
font: {
family: Courier New, monospace, sans-serif;
size: 13px;
};
background: #eee;
white-space: pre-wrap;
padding: 1px 5px;
}
.thumbnail {
background: url('http://i.imgur.com/D8eok3f.jpg') no-repeat center;
background-size: cover;
...
JavaScript
$(".bubble-wrap").on("mousedown", function (e) {
var $this = $(this),
w = Math.sqrt(Math.pow($this.outerWidth(), 2) + Math.pow($this.outerHeight(), 2)) * 2,
mousePosX = e.offsetX === undefined ? e.originalEvent.layerX : e.offsetX,
mousePosY = e.offsetY === undefined ? e.originalEvent.layerY : e.offsetY,
bubble = $('<div class="bubble">');
bubble.css({
"top": (mousePosY - (w / 2)),
"left": (mousePosX - (w / 2)),
"width": w,
"height": w
}).appendTo($this);
var dur = css_to_js_timing(bubble, "animationDuration"),
del = css_to_js_timing(bubble, "animationDelay"),
totalTimeout = dur + del + 10;
setTimeout(function () {
$this.children(".bubble:first").remove();
}, totalTimeout);
});
function css_to_js_timing(el, css_property) {
var el = $(el),
prop = el.css(css_property),
propArr = prop.replace(" ", "").split(","),
propArr_last = propArr[propArr.length - 1];
var val = propArr_last,
multiplier = 1;
if (val.indexOf('s') !== -1 && val.indexOf('ms') == -1) {
multiplier = 1000;
}
var converted = parseInt(parseFloat(val, 10) * multiplier, 10);
return converted;
}
// For Fiddle purposes
$("button").click(function (e) {
e.preventDefault();
});