Roll Those Links!

A rolling effect on links applied via CSS3 3D transforms.

by Akram kamal

HTML

<!-- Throw in a nice looking font just for the fun of it -->
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Yanone+Kaffeesatz:400,700,300,200"/>

<h1>Roll Those Links!</h1>

<p>One way of taming nav links gone wild is to transform a list of links into a select menu for small screens. Here is a clever way to save real estate. <a href="http://jenniferperrin.com/blog/snippet-responsive-menu">Snippet: Responsive Menu</a></p>

<p><a href="http://jenniferperrin.com/blog/quick-and-easy-browser-hacks-using-jquery">Quick and Easy Browser Hacks Using jQuery</a>: Although it is better to use CSS conditionnal comments to detect a specific browser and apply some css style, it is also a very easy thing to do with JQuery...</p>

<p>I thought it would be nice to post a few of the <a href="http://jenniferperrin.com/blog/useful-javascript-jquery-snippets">Useful JavaScript &amp; jQuery Code Snippets</a> I have come across and used with anyone who finds them useful...</p>

<p>Here’s a handy bit of code to <a href="http://jenniferperrin.com/blog/jquery-fade-a-div-after-a-set-time">Fade a div After a Set Amount of Time</a>...</p>

<p>Follow <a href="http://twitter.com/jenniferdperrin">@jenniferdperrin</a> on Twitter →</p>

CSS

body {
    font-family: 'Yanone Kaffeesatz';
    background: #222;
    color: #eee;
    margin: 20px;
    background: #2a2a2a url("http://jenniferperrin.com/image/background.gif") 0 0 repeat;
}
p { margin:10px 0; }
h1 {
    display: block;
    margin: 0 0 20px 15px;
    font-size: 46px;
    font-family: 'Yanone Kaffeesatz';
    color: rgba(255,255,255,0.2);
    text-decoration: none;
}
h1:hover {
    color: rgba(255,255,255,0.3);
}

a {
    color: #f27011;
    text-decoration: none;
}

.roll {
    display: inline-block;
    overflow: hidden;

    vertical-align: top;

    -webkit-perspective: 400px;
       -moz-perspective: 400px;
       -moz-perspective: 400px;

    -webkit-perspective-origin: 50% 50%;
       -moz-perspective-origin: 50% 50%;
            perspective-origin: 50% 50%;
}
.roll span {
    display: block;
    position: relative;
    padding: 0 2px;

    -webkit-transition: all 400ms ease;
       -moz-transition: all 400ms ease;
            transition: all 400ms ease;
    
    -webkit-transform-origin: 50% 0%;
       -moz-transform-origin: 50% 0%;
            transform-origin: 50% 0%;
    
    -webkit-transform-style: preserve-3d;
       -moz-transform-style: preserve-3d;
            transform-style: preserve-3d;
}
    .roll:hover span {
        background: #111;

        -webkit-transform: translate3d( 0px, 0px, -30px ) rotateX( 90deg );
           -moz-transform: translate3d( 0px, 0px, -30px ) rotateX( 90deg );
                transform: translate3d( 0px, 0px, -30px ) rotateX( 90deg );
    }
.roll span:after {
    content: attr(data-title);

    display: block;
    position: absolute;
    left: 0;
    top: 0;
    padding: 0 2px;

    color: #fff;
    background: #bf4c24;

    -webkit-transform-origin: 50% 0%;
       -moz-transform-origin: 50% 0%;
            transform-origin: 50% 0%;

    -webkit-transform: translate3d( 0px, 105%, 0px ) rotateX( -90deg );
       -moz-transform: translate3d( 0px, 105%, 0px ) rotateX( -90deg );
            transform:...

JavaScript

var supports3DTransforms =  document.body.style['webkitPerspective'] !== undefined || 
                            document.body.style['MozPerspective'] !== undefined;

function linkify( selector ) {
    if( supports3DTransforms ) {
        
        var nodes = document.querySelectorAll( selector );

        for( var i = 0, len = nodes.length; i < len; i++ ) {
            var node = nodes[i];

            if( !node.className || !node.className.match( /roll/g ) ) {
                node.className += ' roll';
                node.innerHTML = '<span data-title="'+ node.text +'">' + node.innerHTML + '</span>';
            }
        };
    }
}

linkify( 'a' );