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.

Leave a Reply

Your email address will not be published. Required fields are marked *