From our sponsor: Meco is a distraction-free space for reading and discovering newsletters, separate from the inbox.
Today we will create a set of nice typography effects for big headlines using CSS3 and jQuery. There are many things we can do with CSS3 animations and transitions and we’ll explore some of the possibilites.
We’ll be using Lettering.js in order to style single letters of the words we’ll be having in our big headlines.
The image used in the demo is by Andrey & Lili. They are licensed under the Attribution-NonCommercial 3.0 Unported (CC BY-NC 3.0) License.
Tiny break: 📬 Want to stay up to date with frontend and trends in web design? Subscribe and get our Collective newsletter twice a tweek.
The HTML
The structure will simply be an h2 element with an anchor inside. We’ll wrap the headline in a container:
<div id="letter-container" class="letter-container"> <h2><a href="#">Sun</a></h2> </div>
Then we’ll call the Lettering.js plugin, so that every letter gets wrapped in a span.
Now, let’s take a look at each example. I’ll show all the styles that are relevant to the effect. In the downloadable files, you can check out all the other styles, like the positioning of the headline, the fonts and so on.
In order not to bloat the tutorial, I will not be showing any CSS vendor prefixes. The downloadable files contain them, of course.
Example 1
In the first example we want to skew the letters in order to create bit of perspective. But we also want to change the word on hover, so our structure will contain an additional link element inside of the h2. For the effect to work nicely, we’ll choose two words with the same number of letters:
<div id="letter-container" class="letter-container"> <h2><a href="#">Chaos</a></h2> <h2><a href="#">Order</a></h2> </div>
We’ll give the link element an absolute position and make the second word disappear by giving it the opacity 0:
.letter-container h2 a{ text-align: center; text-transform: uppercase; font-size: 150px; position: absolute; width: 800px; height: 180px; top: 0px; left: 50%; margin-left: -400px; transition: all 0.3s linear; } .letter-container h2 a:nth-child(2){ opacity: 0; }
The spans will have some characteristic text shadow and a transition. The even children of will be skewed 10 degrees and the odd ones -10 degrees:
.letter-container h2 a span{ display: inline-block; position: relative; width: 120px; margin: 0px; transition: all 0.3s linear; text-shadow: 2px 2px 2px rgba(0,0,0,0.6), 1px 1px 2px rgba(0,0,0,0.4), 0px 0px 2px rgba(255,255,255,0.9); } .letter-container h2 a span:nth-child(odd){ transform: skewY(10deg); background: #333; box-shadow: 0px 3px 5px rgba(0,0,0,0.3); z-index: 10; } .letter-container h2 a span:nth-child(even){ transform: skewY(-10deg); background: #666; box-shadow: 0px 3px 5px rgba(0,0,0,0.3); z-index: 10; }
When we hover over the h2 element, we want the second link element to appear and the first to disappear:
.letter-container h2:hover a:nth-child(1){ opacity: 0; } .letter-container h2:hover a:nth-child(2){ opacity: 1; }
Also, we want to straighten the letters out:
.letter-container h2:hover a span{ transform: skewY(0deg); background: #680121; } .letter-container h2 a span:hover{ color: #f6b0c5; }
Example 2
In the second example we’ll play a bit with pseudo elements. First, we’ll style each span in a way to look like a polaroid:
.letter-container h2 a span{ display: inline-block; position: relative; width: 200px; height: 140px; background: #000; line-height: 140px; font-size: 120px; margin: 3px; background-position: 50% 0%; background-size: 200px 267px; color: #fff; text-shadow: 0px 0px 1px #fff, 2px 2px 5px rgba(0,0,0,0.4); border-color: #fff; border-style: solid; border-width: 10px 10px 45px 10px; box-shadow: 2px 2px 8px 4px rgba(0,0,0,0.9), 0px 0px 2px rgba(0,0,0,0.2) inset; transition: all 0.3s ease-in-out; }
We’ll then add a pseudo element that will contain a wicked gradient, making our polaroid look more real:
.letter-container h2 a span:before{ content:''; position: absolute; width: 220px; height: 195px; top: -10px; left: -10px; background: linear-gradient(-45deg, rgba(14,14,14,0.32) 0%,rgba(127,127,127,0.21) 18%,rgba(170,170,170,0.11) 34%,rgba(201,201,201,0) 51%,rgba(242,242,242,0.1) 66%,rgba(255,255,255,0.18) 79%,rgba(71,69,69,0.32) 100%); }
Now, we’ll rotate the odd and even children differently to create a random look:
.letter-container h2 a span:nth-child(even){ transform: rotate(3deg); } .letter-container h2 a span:nth-child(odd){ transform: rotate(-5deg); }
For each character (we are using the classes applied by lettering.js but we could also use the nth-child selector) we will add a different background image:
.letter-container span.char1{ background-image: url(../images/1.jpg); } .letter-container span.char2{ background-image: url(../images/2.jpg); } .letter-container span.char3{ background-image: url(../images/3.jpg); } .letter-container span.char4{ background-image: url(../images/4.jpg); } .letter-container span.char5{ background-image: url(../images/5.jpg); }
On hover over the whole link, we will rotate the spans and scale them down:
.letter-container h2 a:hover span:nth-child(even){ transform: scale(0.9) rotate(-5deg); } .letter-container h2 a:hover span:nth-child(odd){ transform: scale(0.9) rotate(3deg); }
The specific span that we are hovering will have an animation that makes the background image move:
.letter-container h2 a span:nth-child(even):hover, .letter-container h2 a span:nth-child(odd):hover{ animation: moveImg 9s linear infinite forwards; color: rgba(255,255,255,0.4); text-shadow:0px 0px 5px rgba(0,0,0,0.1); transform: scale(1.1); z-index: 10; box-shadow: 2px 2px 20px 4px rgba(0,0,0,0.6), 0px 0px 2px rgba(0,0,0,0.2) inset; } @keyframes moveImg { 0%{ background-position: 50% 0%; } 50%{ background-position: 50% 100%; } 100%{ background-position: 50% 0%; } }
Example 3
In the third example we will apply an animation to the span class which will run once when the page is loaded. We will make a blurry letter become sharp. We will also use a mask to add some texture to the letters (only Webkit browsers currently):
.letter-container h2 a span { font-size: 105px; color: #444; opacity: 1; text-shadow: 0px 0px 2px #444, 1px 1px 4px rgba(0,0,0,0.7); mask-image: url(../images/mask2.png); transition: all 0.3s linear; animation: sharpen 0.6s linear backwards; }
When hovering over a letter we’ll change its color:
.letter-container h2 a span:hover{ color: #3f7f75; }
We’ll create some random appearence of the letters by giving each letter an animation delay:
.letter-container h2 a span:nth-child(1) { animation-delay: 1.2s; } .letter-container h2 a span:nth-child(2) { animation-delay: 0.1s; } .letter-container h2 a span:nth-child(3) { animation-delay: 1s; } /* ... and so on for all the letters */
The animation makes the letter appear blurry with a text-shadow with high fuzziness and a transparent color. Then it will appear sharpened by turning into a letter with solid color and a subtle text shadow:
@keyframes sharpen { 0% { opacity: 0; text-shadow: 0px 0px 100px #444; color: transparent; } 90% { opacity: 0.9; text-shadow: 0px 0px 10px #444; color: transparent; } 100% { color: #444; opacity: 1; text-shadow: 0px 0px 2px #444, 1px 1px 4px rgba(0,0,0,0.7); } }
Example 4
This example is quite different from all the others because we will apply some more jQuery. To understand what we are doing, I will show you what our jQuery function is making out of the headline. The structure that is created for each letter span after we apply lettering.js is the following:
<div class="twrap"> <div class="tbg"><span>P</span></div> <div class="tup"> <div class="tfront"><span>P</span></div> <div class="tback"><span>P</span></div> </div> <div class="tdown"><span>P</span></div> </div>
Now, why such a structure? We want to play with perspective and 3d transforms, so we need a few more elements to make this work.
We want this headline to look like an airport information board and when we hover over a span, we want the little top element to fall down, but in 3D! This will only work in a Webkit browser, but we will have a nice alternative for the others.
So, let’s start by styting that new wrapper. It will be the container with the persepctive:
.letter-container h2 .twrap{ position: relative; display: inline-block; width: 100px; height: 120px; line-height: 120px; font-size: 120px; border: 15px solid rgba(0,0,0,0.5); -webkit-perspective: 400; box-shadow: 1px 1px 4px #000; }
Then we’ll style the background letter, which will be yellow:
.letter-container h2 .tbg{ background: #121212; position: absolute; color: #f2c200; width: 100%; height: 100%; box-shadow: 0px 1px 3px rgba(0,0,0,0.9); }
The down part of the letter in both the “tdown” and the “tup” (“tback”) container will be pulled up with a negative margin, because we just want to show the lower part:
.letter-container h2 .tdown{ height: 50%; top: 50%; width: 100%; position: absolute; overflow: hidden; z-index: 1; background: #151515; box-shadow: 0px 1px 3px rgba(0,0,0,0.9); transition: all 0.3s linear; } .letter-container h2 .tdown span, .letter-container h2 .tup .tback span{ display: block; margin-top:-60px; }
All the elements will have an aboslute position. The elements inside of “tup” will have -webkit-backface-visibility: hidden. Like that we’ll be able to rotate “tback” in 3d space and then “tup” when we hover:
.letter-container h2 .tup{ height: 50%; width: 100%; position: absolute; z-index: 10; -webkit-transform-origin: 50% 100%; transition: all 0.3s linear; box-shadow: 0px 1px 3px rgba(0,0,0,0.9); } .letter-container h2 .tup .tfront, .letter-container h2 .tup .tback{ position: absolute; width: 100%; height: 100%; top: 0px; overflow: hidden; -webkit-backface-visibility: hidden; background: #151515; } .letter-container h2 .tup .tback{ background: #121212; color: #f2c200; } .csstransforms3d .letter-container h2 .tup .tback{ -webkit-transform: rotateX(-180deg); } .csstransforms3d .letter-container h2 a .twrap:hover .tup{ -webkit-transform: rotateX(-180deg); }
When we dont’ have support for the 3d transform then we’ll not show “tback”. We’ll instead animate “tup” and “tdown” to move to the back:
/* For browsers with no 3d transfrom support */ .no-csstransforms3d .letter-container h2 .tup .tback{ display: none; } .no-csstransforms3d .letter-container h2 a .twrap:hover .tup{ animation: moveBackUp 0.7s ease-in-out forwards; } .no-csstransforms3d .letter-container h2 a .twrap:hover .tdown{ animation: moveBackDown 0.7s ease-in-out forwards; } @keyframes moveBackUp { 0%{ transform: translateY(0%); } 50%{ transform: translateY(-120%); z-index: -1; } 100%{ transform: translateY(0%); z-index: -1; } } @keyframes moveBackDown { 0%{ transform: translateY(0%); } 50%{ transform: translateY(120%); z-index: -1; } 100%{ transform: translateY(0%); z-index: -1; } }
Example 5
Ok, example 5 looks crazy: we’ll create a text shadow that “elevates” the letters. We’ll also create a pseudo element which has a superhero as background:
.letter-container h2 a:before{ content: ''; position: absolute; z-index: 0; width: 525px; height: 616px; background: transparent url(../images/superhero.png) no-repeat center center; background-size: 40%; top: 0px; left: 50%; margin-left: -277px; transition: all 0.3s ease-in-out; }
On hover, we will animate the background size to make the superhero larger:
.letter-container h2 a:hover:before{ background-size: 100%; }
The span will have the text-shadow that “elevates” the letters and on hover, we will move the letter down by adding a padding and changing the shadow:
.letter-container h2 a span{ color: #ff3de6; float:left; position: relative; z-index: 100; transition: all 0.3s ease-in-out; text-shadow: 0px -1px 3px #cb4aba, 0 4px 3px #934589, 2px 15px 5px rgba(0, 0, 0, 0.2), 1px 20px 10px rgba(0, 0, 0, 0.3); } .letter-container h2 a span:hover{ color: #e929d0; padding-top: 10px; text-shadow: 0px -1px 3px #cb4aba, 0 4px 3px #934589, 1px 1px 10px rgba(0, 0, 0, 0.2); }
Example 6
In this example we’ll do something similar like in demo 3, except that we’ll animate the letters in order.
We’ll also apply a mask that will give some texture to the letters:
.letter-container h2 a { text-align: center; font-size: 130px; line-height: 160px; display: block; padding-bottom: 30px; mask: url(../images/mask.png) repeat; }
The animation will sharpen the letters and we will apply a different animation delay to each child:
.letter-container h2 a span { color: #fff; opacity: 1; text-shadow: 0px 0px 2px #fff, 1px 1px 4px rgba(0,0,0,0.7); transition: all 0.3s linear; animation: sharpen 0.9s linear backwards; } .letter-container h2 a span:hover{ text-shadow: 0px 0px 40px #fff; } .letter-container h2 a span:nth-child(1) { animation-delay: 0s; } .letter-container h2 a span:nth-child(2) { animation-delay: 0.1s; } .letter-container h2 a span:nth-child(3) { animation-delay: 0.2s; } /* ...and so on for all the letters */ @keyframes sharpen { 0% { opacity: 0; text-shadow: 0px 0px 100px #fff; color: transparent; } 90% { opacity: 0.9; text-shadow: 0px 0px 10px #fff; color: transparent; } 100% { color: #fff; opacity: 1; text-shadow: 0px 0px 2px #fff, 1px 1px 4px rgba(0,0,0,0.7); } }
Example 7
In the last example we’ll create some circles for each letter and on hover we will add a radial gradient to make it appear as a sun:
.letter-container h2 a span{ display: inline-block; background: #bfd4e2; color: #ecf0f2; text-shadow: 1px 1px 2px rgba(120,155,179,0.5); width: 200px; height: 200px; line-height: 200px; font-size: 100px; margin: 3px; cursor: pointer; border-radius: 50%; box-shadow: 2px 2px 10px rgba(43,54,61, 0.4), 0px 0px 0px 9px rgba(116,161,191,0.3) inset; transition: all 0.3s ease-in-out; } .letter-container h2 a:hover span{ opacity: 0.3; }
You can read a great explanation of the radial gradient here: CSS3 Radial Gradient Syntax Breakdown – Impressive Webs
.letter-container h2 a span:hover{ opacity: 1; box-shadow: 2px 2px 10px rgba(43,54,61, 0.4), 0px 0px 0px 0px #fedc3f inset, 0px 0px 100px 30px rgba(255,244,193,0.8); color: #ff8624; text-shadow: 1px 1px 2px rgba(166,97,41,0.5), 1px 1px 1px #e66212, 3px 3px 1px #fdff64, 4px 4px 6px #ff7420; background-image: radial-gradient( center center, circle contain, #fedc3f 0%, #ff7420 100% ); }
And that’s it! I hope you enjoyed creating some crazy typography effects with CSS3 and jQuery!
What’s your favorite one?
It’s a nice post.
amazing, looking great on Firefox
but it is not working properly on IE 8