I've been playing around with the idea of applying CSS3 transforms and other effects to individual letters in a string, and I wanted a flexible way to do this that didn't involve any special markup from the content author.
After testing some ideas I settled on writing a small jQuery plugin to handle the task of wrapping each letter of a string in its own span. I call the plugin Span Letters, and it looks like this:
( function( $ ) { // Example usage: jQuery( '.selector' ).spanLetters(); $.fn.spanLetters = function() { // Loop through each element on which this function has been called this.each( function() { // Make an array with each letter of the string as a value var words = $( this ).text().split( '' ); // Loop through the letters and wrap each one in a span for ( i = 0; i in words; i++ ) { words[i] = '<span class="sl' + (i + 1) + ' span-letter">' + words[i] + '</span>' }; // Join our array of span-wrapped letters back into a string var text = words.join( '' ); // Replace the original string with the new string $( this ).html( text ); }) } }( jQuery ));
This will wrap each letter in a span and give the span a unique sequential class that we can use to apply our individual letter styling. Of course we can also use something like span:nth-child() instead of using the sequential classes. We can bring this to life with some CSS like this:
.container { font-family: verdana; font-weight: bold; text-shadow: -1px 0 0px #FFADDA, 0 1px 0px #F99ACD, -2px 1px 0px #FFADDA, -1px 2px 0px #F99ACD, -3px 2px 0px #FFADDA, -2px 3px 0px #F99ACD, -4px 3px 0px #FFADDA, -3px 4px 0px #F99ACD, -5px 4px 0px #FFADDA, -4px 5px 0px #F99ACD, -6px 5px 0px #FFADDA, -5px 6px 15px #000000; text-transform: uppercase; } .container span { display: inline-block; transition: 0.8s; } .container .sl1 { color: red; transform: rotateX( 20deg ) rotateY( -20deg ) rotateZ( 10deg ); } .container .sl2 { color: orange; transform: rotateX( 0deg ) rotateY( 0deg ) rotateZ( -15deg ); } .container .sl3 { color: yellow; transform: rotateX( 0deg ) rotateY( 30deg ) rotateZ( 25deg ); } .container .sl4 { color: green; transform: rotateX( 0deg ) rotateY( 5deg ) rotateZ( -5deg ); } .container .sl5 { color: blue; transform: rotateX( 20deg ) rotateY( 0deg ) rotateZ( -35deg ); } .container .sl6 { color: indigo; transform: rotateX( 10deg ) rotateY( 0deg ) rotateZ( 5deg ); } .container .sl7 { color: violet; transform: rotateX( 0deg ) rotateY( 30deg ) rotateZ( 35deg ); } .container .sl8 { color: white; transform: rotateX( -10deg ) rotateY( 0deg ) rotateZ( -15deg ); } .container .sl9 { color: black; transform: rotateX( -10deg ) rotateY( 0deg ) rotateZ( 15deg ); } .container:hover span { transform: rotateX( 0deg ) rotateY( 0deg ) rotateZ( 0deg ); cursor: pointer; }
To create this:
Transform
Hover/Tap to revert to normal
That's pretty neat, but how can we make this more functional? I like the idea of transitioning into or out of the effect when the user hovers over the text. Here are some examples:
Example 1 - 2D Spinning Letters
.container { font-family: verdana; font-weight: bold; text-shadow: -1px 0 0px #FFADDA, 0 1px 0px #F99ACD, -2px 1px 0px #FFADDA, -1px 2px 0px #F99ACD, -3px 2px 0px #FFADDA, -2px 3px 0px #F99ACD, -4px 3px 0px #FFADDA, -3px 4px 0px #F99ACD, -5px 4px 0px #FFADDA, -4px 5px 0px #F99ACD, -6px 5px 0px #FFADDA, -5px 6px 15px #000000; text-transform: uppercase; color: white; } .container span { display: inline-block; transition: 0.8s; } .container:hover span:nth-child(odd) { transform: rotateX( 0deg ) rotateY( 0deg ) rotateZ( 370deg ); cursor: pointer; } .container:hover span:nth-child(even) { transform: rotateX( 0deg ) rotateY( 0deg ) rotateZ( -370deg ); cursor: pointer; }Result:
Transform
Hover/Tap for effect
Example 2 - 3D Spinning Letters
.container { font-family: verdana; font-weight: bold; text-shadow: -1px 0 0px #FFADDA, 0 1px 0px #F99ACD, -2px 1px 0px #FFADDA, -1px 2px 0px #F99ACD, -3px 2px 0px #FFADDA, -2px 3px 0px #F99ACD, -4px 3px 0px #FFADDA, -3px 4px 0px #F99ACD, -5px 4px 0px #FFADDA, -4px 5px 0px #F99ACD, -6px 5px 0px #FFADDA, -5px 6px 15px #000000; text-transform: uppercase; color: white; } .container span { display: inline-block; transition: 1.5s; } .container:hover span:nth-child(odd) { transform: rotateX( 0deg ) rotateY( 370deg ) rotateZ( 370deg ); cursor: pointer; } .container:hover span:nth-child(even) { transform: rotateX( -370deg ) rotateY( 0deg ) rotateZ( -370deg ); cursor: pointer; }Result:
Transform
Hover/Tap for effect
Example 3 - The Gangster Lean
.container { font-family: verdana; font-weight: bold; text-transform: uppercase; color: #545454; } .container span { display: inline-block; transition: 1s; } .container:hover span { transform: skewX( -10deg ) translateX( 10px ); cursor: pointer; }Result:
Transform
Hover/Tap for effect
Example 4 - Individual Letter Scaling
.container { font-family: verdana; font-weight: bold; text-shadow: -1px 0 0px #FFADDA, 0 1px 0px #F99ACD, -2px 1px 0px #FFADDA, -1px 2px 0px #F99ACD, -3px 2px 0px #FFADDA, -2px 3px 0px #F99ACD, -4px 3px 0px #FFADDA, -3px 4px 0px #F99ACD, -5px 4px 0px #FFADDA, -4px 5px 0px #F99ACD, -6px 5px 0px #FFADDA, -5px 6px 15px #000000; text-transform: uppercase; color: white; } .container span { display: inline-block; transition: 0.8s; } .container:hover span { cursor: pointer; position: relative; } .container:hover .sl1 { transform: scale(1.25); z-index: 4; } .container:hover .sl2 { transform: scale(1.15); z-index: 3; } .container:hover .sl3 { transform: scale(1.05); z-index: 2; } .container:hover .sl4 { transform: scale(0.95); z-index: 1; } .container:hover .sl5 { transform: scale(0.85); z-index: 0; } .container:hover .sl6 { transform: scale(0.95); z-index: 1; } .container:hover .sl7 { transform: scale(1.05); z-index: 2; } .container:hover .sl8 { transform: scale(1.15); z-index: 3; } .container:hover .sl9 { transform: scale(1.25); z-index: 4; }Result:
Transform
Hover/Tap for effect
Example 5 - Text-Shadow Animations
.container { font-family: verdana; font-weight: bold; text-transform: uppercase; color: rgba(210, 210, 210, 0.6); text-shadow: 1px 2px 6px #FFFFFF, 0 0 0 #000000; } .container span { transition: 0.3s; display: inline-block; } .container:hover span { cursor: pointer; color: rgba(200, 200, 200, 0.6); text-shadow: 3px 6px 10px #FFFFFF, 0 0 0 #000000; }Result:
Transform
Hover/Tap for effect
With each letter wrapped in a span, the possibilities are endless.
-Braad