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