Quick and easy creative typography animation tutorial
Live preview, hover over buttons:
Full video guide: https://www.youtube.com/watch?v=GAda7CsMrTE
- 1) Let’s start with HTML markup. We will separate the first letter with <span> tags so we can animate it independently…
<div class="button">
<p><span>H</span>ome</p>
</div>
… and give it basic CSS
.button {
margin: 30px;
width: 160px;
height: 60px;
border: 1px solid black;
}
2) Align the text inside
.button p {
line-height: 60px;
text-align: center;
font-size: 25px;
font-weight: 900;
}
3) Now we do a little hack. We want to animate the first letter without affecting the alignment of the rest of the word. We have already separated the first letter with <span> element. Let’s make the letter itself invisible and give the <span> element position property, so we can attach another absolutely positioned element to it:
.button span {
color: transparent;
position: relative;
}
Display the actual letter inside with a help of ::before pseudo element
.button span::before {
content: 'H';
position: absolute;
width: auto;
height: 60px;
color: black;
}
This way our text stays aligned correctly and we are free to animate the first letter however we want without causing layout re-flow.

4) Next we want to create black block the same size of our button, which will appear and slowly rotate on hover. Give the button relative position
.button {
...
position: relative;
}
… and create a block using ::after pseudo element. At first it’s hidden with 0 opacity – background-color: rgba(0,0,0,0);
.button::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0);
transition: .8s;
z-index: 1;
}
5) To create our hover effect we need to do few things. First we need to push the text in front of the black block. Z-index only works on elements with position property:
.button p {
...
position: relative;
transition: .8s;
z-index: 10;
}
We will also be animating <span>::before element that holds the first letter. Let’s give it transition property:
.button span::before {
...
transition: .2s ease-out;
}
We want the black box to rotate slowly on hover, become visible and our text in <p> and <span> elements to turn white:
.button:hover::after {
background-color: rgba(0,0,0,1);
transform: rotate(10deg);
}
.button:hover p {
color: white;
}
.button:hover span::before {
color: white;
}

6) Finally we animate the first letter. You can experiment with this, I decided to make it rotate 360 degrees
.button:hover span::before {
color: white;
transform: translate(-65%, -10%) rotate(360deg);
font-size: 80px;
}

Thank you for reading, more guides coming soon!
Final HTML:
<div class="container">
<div class="button">
<p><span>H</span>ome</p>
</div>
<div class="button">
<p><span>P</span>roducts</p>
</div>
<div class="button">
<p><span>A</span>bout</p>
</div>
<div class="button">
<p><span>C</span>ontact</p>
</div>
</div>
Final CSS:
body {
background-color: white;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
.container {
position: relative;
margin: 0 auto;
width: 160px;
}
.button {
margin: 30px;
width: 160px;
height: 60px;
border: 1px solid black;
position: relative;
}
.button p {
position: relative;
transition: .8s;
line-height: 60px;
text-align: center;
font-size: 25px;
font-weight: 900;
z-index: 10;
}
.button span {
color: transparent;
position: relative;
}
.button span::before {
content: 'H';
position: absolute;
width: auto;
height: 60px;
color: black;
transition: .2s ease-out;
}
.button:nth-of-type(2) span::before {
content: 'P';
}
.button:nth-of-type(3) span::before {
content: 'A';
}
.button:nth-of-type(4) span::before {
content: 'C';
}
.button::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0);
transition: .8s;
z-index: 1;
}
.button:hover::after {
background-color: rgba(0,0,0,1);
transform: rotate(10deg);
}
.button:hover p {
color: white;
}
.button:hover span::before {
color: white;
transform: translate(-65%, -10%) rotate(360deg);
font-size: 80px;
}
Leave a Reply