This week, a colleague of mine asked whether it was possible to animate the CSS text-align
property using CSS transitions. My immediate response was of course “no!”, but despite having said that I had a nagging suspicion it was in fact achievable in some (as yet unknown) way.
Given that the animation was fairly critical to a project he was working on, I took 5 minutes to attempt to find a solution.
The Requirement
The problem I had to solve was to find a way of animating a heading element from the center to the left hand edge of a box of unknown (flexible) width.
The markup for this was as follows:
<div class="container">
<h1>Heading Here</h1>
</div>
A first pass
The first thing I needed to do was find a way to mimic text-align: center
without using the text-align
property. Thinking back to old skool techniques for centrally aligning content, I immediately turned to CSS positioning applying position: relative
to the heading and shifting it 50% to the right. I then added a transform: translateX(-25%)
to shift the heading back by 25%.
h1 {
position: relative;
left: 50%;
transform: translateX(-25%);
}
The result wasn’t bad and gave a good approximation on centralising the heading, but it didn’t function reliably as the containing box flexed in size. Clearly a no go. Back to the drawing board.
A refined approach
Musing upon my previous effort I realised I’d need to focus more on the flexible containing box. Specifically, I needed to make the heading aware of its container’s width so that any positioning shifts on the heading would be inline with the size of the containing box.
To do this I applied display: block
to the heading to force it to occupy 100% of the width of the containing box. I then applied the the same 50% left shift to shunt the heading so that it’s left hand edge started at the middle of the containing box.
Next I needed to shift the text of the heading back by half its own width (the inner text not the heading itself). This is the key to the technique. By wrapping the heading text with a tag with
display: inline-block
I now had an element which wrapped the width of the content only. With this in place I simply added transform: translateX(-50%)
to move the text back across by half its own width.
The last step was to replace the position: relative; left: 50%;
on the heading element with a simpler transform: translateX(50%)
.
h1 {
display: block;
transform: translateX(50%);
}
span {
display: inline-block; // critical
transform: translateX(-50%); // shift back by 50% of the *text* width
}
The result is text alignment that mimics text-align: center
but using only properties which are animatable.
Animating the Text Alignment
The last step was animating the alignment. To do this I set the translateX
values on both the heading and span to 0% upon the addition of an .active
class to the heading element. This effectively removed the alignment hack returning the text to the default left alignment.
From here I simply had to apply a transition
to animate the transforms for both heading and child span in tandem.
Voila! Animateable text alignment using pure CSS.
To see the effect working in full, check out the Codepen example.
Did this technique work for you? Let me know in the comments.
Thanks for this article. Found this helpful for a Cohort project.