Animatable: One property, two values, endless possibilities
Animatable
One property, two values, endless possibilities
box-shadow
◀
▶
- From:
- 0 0 black
- To:
- 0 150px 10px -50px rgba(0,0,0,.5)
- Author:
- @leaverou
* {
margin: 0;
}
body {
padding: 1em 5em;
font: 1em/1.5em Futura, 'Century Gothic', sans-serif;
text-align: center;
overflow-x: hidden;
}
hgroup > h1 {
font-size: 500%;
line-height: 1;
text-transform: lowercase;
}
hgroup > h2 {
font-size: 120%;
}
a {
text-decoration: none;
color: slategray;
}
div[role="main"] {
padding: 2em .5em;
counter-reset: demo;
}
div[role="main"]:after {
content: '';
display: block;
clear: both;
}
a[data-property] {
position: relative;
float: left;
width: 150px;
height: 150px;
box-sizing: border-box;
margin: 0 15px 30px;
background: slategray;
color: white;
font-size: 60px;
line-height: 150px;
text-align: center;
counter-increment: demo;
}
body.in-page a[data-property]:not(:target) {
opacity: .2 !important;
}
#on-hover:checked ~ div[role="main"] > a[data-property]:not(:hover):not(:target),
body.in-page a[data-property]:not(:target) {
animation: none !important;
}
a[data-property]:after {
content: attr(data-property);
position: absolute;
right: 0;
left: 0;
bottom: -1.2em;
z-index: 2;
color: slategray;
font-size: 14px;
line-height: 1;
text-indent: 0;
text-shadow: none;
letter-spacing: 0;
}
a[data-property]:before {
content: counter(demo);
}
input[type="radio"] {
position: absolute;
clip: rect(0,0,0,0);
}
input[type="radio"] + label {
display: inline-block;
padding: .3em .7em;
border: 1px solid rgba(0,0,0,.3);
margin-top: 1em;
background: #809070;
color: white;
text-shadow: .05em .05em .2em rgba(0,0,0,.8);
cursor: pointer;
border-radius: .3em;
box-shadow: 0 1px rgba(255,255,255,.6) inset;
}
input[type="radio"]:not(:checked) + label {
background-image: linear-gradient(rgba(255,255,255,.3), rgba(255,255,255,0));
}
input[type="radio"]:checked + label {
box-shadow: .05em .05em .4em .1em rgba(0,0,0,.8) inset;
}
.in-page input[type="radio"] + label {
display: none;
}
#info {
position: absolute;
z-index: 2;
width: 510px;
height: 150px;
padding: 10px 15px;
box-sizing: border-box;
overflow: hidden;
background: black;
color: white;
text-align: left;
transition:.5s;
}
.home > #info {
display: none;
}
#info h1 {
color: slategray;
margin-bottom: .3em;
}
#info > a {
position: absolute;
top: 10px;
right: 10px;
width: 2em;
line-height: 2;
font-size: 80%;
background: rgba(255,255,255,.25);
color: black;
text-align: center;
border-radius: 0 50% 50% 0;
}
#info > a:hover {
background: #809070;
}
#info > a[title="Previous"] {
right: 36px;
border-radius: 50% 0 0 50%;
}
dl {
font-size: 80%;
}
dl:after {
content: '';
display: block;
clear: both;
}
dt {
float: left;
clear: left;
width: 6em;
color: gray;
}
dd {
float: left;
clear: right;
white-space: nowrap;
}
dd > a {
color: inherit;
}
dd > a > img {
margin-right: 5px;
vertical-align: -8px;
border-radius: 12px;
}
.twitter-share-button {
position: fixed;
top: 10px;
left: 10px;
}
.github-ribbon {
position: absolute;
top: 0;
right: 0;
}
function $(expr, con) { return (con || document).querySelector(expr); }
function $$(expr, con) { return [].slice.call((con || document).querySelectorAll(expr)); }
var css = [];
$$('a[data-property]').forEach(function(el, i){
var property = el.getAttribute('data-property'),
from = el.getAttribute('data-from'),
to = el.getAttribute('data-to');
var id = property, i = 1;
while(document.getElementById(id)) {
id = property + '/' + ++i;
}
el.id = id;
el.href = '#' + id;
el.title = property + ' from ' + from + ' to ' + to;
var selector = '#' + id.replace(/([^\w-])/g, '\\$1'),
ident = id.replace(/([^\w-])/g, '-');
css.push('@keyframes ' + ident + '{',
'from{' + property + ':' + from + '}',
'to{' + property + ':' + to + '}}',
selector + ' { animation: ' + ident + ' 1s infinite alternate;' + property + ':' + from + '}');
});
var style = document.createElement('style');
style.textContent = css.join('\r\n');
StyleFix.styleElement(style);
document.head.appendChild(style);
setTimeout(onhashchange = function() {
var target = location.hash? $(location.hash.replace(/([^\w-#])/g, '\\$1')) : null;
if(!target) {
document.body.className = 'home';
return;
}
document.body.className = 'in-page';
var info = $('#info'),
previous = target.previousElementSibling,
next = target.nextElementSibling,
author = target.getAttribute('data-author') || 'leaverou';
$('h1', info).innerHTML = target.getAttribute('data-property');
$('dd:first-of-type', info).innerHTML = target.getAttribute('data-from');
$('dd:nth-of-type(2)', info).innerHTML = target.getAttribute('data-to');
$('dd:nth-of-type(3)', info).innerHTML = '@' + author + '';
$('a[title="Previous"]', info).setAttribute('href', '#' + (previous? previous.id : ''));
$('a[title="Next"]', info).setAttribute('href', '#' + (next? next.id : ''));
setTimeout(function() {
if(2*target.offsetLeft + target.offsetWidth < innerWidth) {
info.style.left = target.offsetLeft + target.offsetWidth + 30 + 'px';
}
else {
info.style.left = target.offsetLeft - info.offsetWidth - 30 + 'px';
}
info.style.top = target.offsetTop + 'px';
}, 10);
}, 50);
onkeyup = function(evt) {
var key = evt.keyCode;
switch (key) {
case 27:
location.hash = '';
break;
case 37:
case 38:
location.hash = location.hash? $('a[title="Previous"]').hash : $('a[data-property]:last-child').hash;
break;
case 39:
case 40:
location.hash = location.hash? $('a[title="Next"]').hash : $('a[data-property]:first-child').hash;
}
};