http://www.zhangxinxu.com/wordpress/2011/11/css3-prefixfree-js-animatable/
http://leaverou.github.io/animatable/
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Animatable: One property, two values, endless possibilities</title> <style type="text/css"> * { 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; outline-color: transparent; } 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; } </style> <script src="http://leaverou.github.com/prefixfree/prefixfree.min.js"></script> </head> <body> <hgroup> <h1><a href="#">Animatable</a></h1> <h2>One property, two values, endless possibilities</h2> </hgroup> <input type="radio" name="animate" id="on-hover" checked /> <label for="on-hover">Animate on hover</label> <input type="radio" name="animate" id="all" /> <label for="all">Animate all</label> <div role="main"> <a data-property="background-color" data-from="slategray" data-to="black"></a> <a data-property="background-position" data-from="0 0" data-to="100% 100%" style="background-image: linear-gradient(135deg, transparent 25%, black 25%, black 50%, transparent 50%, transparent 75%, black 75%, black); background-size:50px 50px"></a> <a data-property="background-position" data-from="3px 0, 3px 0, 15px -150px, 15px -150px" data-to="3px -70px, 3px -70px, 15px -80px, 15px -80px" style="background-color: #E04332; background-repeat: repeat-x; background-size: 24px 300px; background-image: linear-gradient(135deg, slategray 25%, transparent 25%), linear-gradient(45deg, transparent 75%, slategray 75%), linear-gradient(45deg, slategray 25%, transparent 25%), linear-gradient(135deg, transparent 75%, slategray 75%);" data-author="kizmarh"></a> <a data-property="background-size" data-from="5px 5px" data-to="150px 150px" style="background-image: repeating-radial-gradient(transparent, transparent 9px, black 11px, black 20px); background-position:center"></a> <a data-property="border-radius" data-from="0" data-to="50%"></a> <a data-property="border-radius" data-from="0 100%" data-to="100% 0"></a> <a data-property="border-width" data-from="0" data-to="75px" style="border-style:solid; border-color: black;"></a> <a data-property="border-width" data-from="0" data-to="35px" style="border-style:dashed; border-color: black;"></a> <a data-property="border-width" data-from="0" data-to="75px" style="border-style:double; border-color: black;"></a> <a data-property="box-shadow" data-from="0 0 black" data-to="0 150px 10px -50px rgba(0,0,0,.5)"></a> <a data-property="box-shadow" data-from="none" data-to="inset -75px -75px 400px #000" data-author="yuritkachenko"></a> <a data-property="box-shadow" data-from="inset 0 0 75px 75px slategray, 0 0 0 slategray" data-to="inset 0 0 35px 35px transparent, 0 0 75px 50px transparent" style="background: transparent; border-radius: 1px;" data-author="kizmarh"></a> <a data-property="color" data-from="white" data-to="black"></a> <a data-property="font-size" data-from="60px" data-to="300px"></a> <a data-property="height" data-from="150px" data-to="0"></a> <a data-property="letter-spacing" data-from="0" data-to="100px"></a> <a data-property="line-height" data-from="10px" data-to="300px"></a> <a data-property="opacity" data-from="1" data-to="0"></a> <a data-property="outline-width" data-from="0" data-to="100px" style="outline-color:black; outline-style: solid;"></a> <a data-property="outline-offset" data-from="-5px" data-to="30px" style="outline-style: dashed; outline-color:slategray;" data-author="mkuehnel"></a> <a data-property="outline-color" data-from="transparent" data-to="red" style="outline-width: 30px; outline-style: solid;" data-author="mkuehnel"></a> <a data-property="padding" data-from="0" data-to="50px 200px 50px 50px" data-author="steno"></a> <a data-property="text-indent" data-from="0" data-to="100px"></a> <a data-property="text-shadow" data-from="0 0 black" data-to="20px 20px 10px rgba(0,0,0,.5)"></a> <a data-property="text-shadow" data-from="0 0 0 white" data-to="0 0 10px white" style="color: transparent;" data-author="bartaz"></a> <a data-property="text-shadow" data-from="0 0 white" data-to="0 0 rgba(255,255,255,0), -45px -45px 0 red, -30px -30px 0 orange, -15px -15px 0 yellow, 0 0 0 green, 15px 15px 0 blue, 30px 30px 0 indigo, 45px 45px 0 violet" style="color: transparent" data-author="kizmarh"></a> <a data-property="top" data-from="0" data-to="100px" style="position:relative"></a> <a data-property="transform" data-from="rotate(0deg)" data-to="rotate(360deg)"></a> <a data-property="transform" data-from="scale(1)" data-to="scale(2)"></a> <a data-property="transform" data-from="skewX(0deg)" data-to="skewX(180deg)"></a> <a data-property="transform" data-from="rotate(0deg) scale(1)" data-to="rotate(360deg) scale(0)"></a> <a data-property="transform" data-from="perspective(400px) rotateY(0deg)" data-to="perspective(400px) rotateY(360deg)"></a> <a data-property="transform" data-from="perspective(400px) rotateX(0deg)" data-to="perspective(400px) rotateX(360deg)" data-author="calvein"></a> <a data-property="transform" data-from="perspective(400px) rotateY(0deg)" data-to="perspective(400px) translateZ(150px) rotateY(180deg)" data-author="bartaz"></a> <a data-property="transform" data-from="perspective(400px) translate3d(0,0,0) rotateX(0) rotateY(0) rotateZ(0)" data-to="perspective(400px) translate3d(0,0,-5000px) rotateX(720deg) rotateY(360deg) rotateZ(-360deg)" data-author="bartaz"></a> <a data-property="transform" data-from="perspective(400px) rotate3d(1,1,0,0deg)" data-to="perspective(400px) rotate3d(1,1,0,180deg)" data-author="bartaz"></a> <a data-property="transform" data-from="perspective(400px) rotate3d(0,1,0,0deg)" data-to="perspective(400px) rotate3d(0,1,0,-180deg)" data-author="filipearaujo" style="transform-origin: 100% 50%;"></a> <a data-property="transform-origin" data-from="50% 50%" data-to="0 100%" style="transform:rotate(45deg)"></a> <a data-property="width" data-from="150px" data-to="330px" data-author="mkuehnel"></a> </div> <section id="info"> <h1>box-shadow</h1> <a href="#" title="Previous">◀</a> <a href="#" title="Next">▶</a> <dl> <dt>From:</dt> <dd>0 0 black</dd> <dt>To:</dt> <dd>0 150px 10px -50px rgba(0,0,0,.5)</dd> <dt>Author:</dt> <dd>@leaverou</dd> </dl> </section> <footer>Made by <a href="http://lea.verou.me">Lea Verou</a> with care</footer> <script> 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 = '<a href="http://twitter.com/' + author + '" target="_blank"><img src="http://twitter.com//api/users/profile_image?screen_name=' + author + '&size=mini"/>@' + author + '</a>'; $('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; } }; </script> <a href="https://github.com/leaverou/animatable" target="_blank" class="github-ribbon"> <img src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub"> </a> <a href="https://twitter.com/share" class="twitter-share-button" data-count="vertical" data-via="LeaVerou">Tweet</a> <script src="https://platform.twitter.com/widgets.js"></script> <script src="http://www.google-analytics.com/ga.js"></script> <script> try { var pageTracker = _gat._getTracker("UA-597483-5"); pageTracker._trackPageview(); } catch(err) {} </script> </body> </html>