Quick Introduction

Back in the days, before the CSS3 and its power were unleashed, web animations were heavily dependant on the JavaScript and without it, developers were limited to simple things like color and border "animations" without the smooth transitions between the two states on the animated element. The most common CSS effect was, and possibly still is, the situation where we change the element background color when the user hovers over it. This was made possible by the :hover pseudo-class. As soon as we needed something more complex, like fade or slide effect, we were required to use JavaScript.

Further on, things like text animations were impossible to do by using pure CSS, but luckily, we have reached the point where the industry has evolved and by doing so enriched the CSS with a lot of new cool and useful features. In this article, we will animate our text by using CSS only. To be more precise, we will use transition and transform properties.

Transitions enable us to define the transition between two states of an element. Different states may be defined using pseudo-classes like :hover or :active

This is very useful. When we change the element width, for example, we can set the way how the width will be changed in terms of duration, timing, and delay.

The transform CSS property lets us rotate, scale, skew or translate an element

In our example, we will use the scale option because we need to handle the size of an element (lines "moving" from top left corner), and believe it or not, these two properties are all we need for it. Everything else is standard CSS like width, position, opacity...etc. The difference is that we can animate them and set the transition between the states, as described above.

Ok, I think we are ready to dive into the implementation. Feel free to copy & paste the code and change it to fit your needs. Enjoy!


<div class="box">
    <span class="l-top"></span>
    <span class="l-left"></span>
    <div class="box-inner">
      <span class="hover-me">Hover me!</span>
      <span class="hi">Hi!</span>
      <span class="message">Welcome to the No JS Text Animation</span>
    <span class="l-right"></span>
    <span class="l-bottom"></span>
<div class="box box-next">
	Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
	Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
	Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
	Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

In our HTML, each span element within the first box, and the entire second box is going to be animated. In the first box, the text will slide from left to the right and fade in during the process. The text will be surrounded by animated lines forming a box originating from the top left corner. Each line will have its animation duration and direction. Pretty neat, right?

The second box will slide down with an arrow pointing towards it from the original text. And all this WITHOUT a single JavaScript line of code.

The entire CSS implementation looks like this:


.box {
    margin: 0 auto;
    position: relative;
    color: #feb090;
    width: 570px;
    height: 50px;
    font-size: 2rem;
    box-sizing: border-box;

.box-inner {
    position: relative;

.box-next {
    opacity: 0;
    transition: all 1s ease;
    font-size: inherit

.box > div > span, .box > span {
    display: block;
    transition: all 1s ease;
    position: absolute;
    left: 0;
    width: 100%;
    height: 100%;

.box > div > span {

.box > div > span:not(:first-child) {
    opacity: 0;

.box > div > span.hover-me {
    transition-duration: .1s;

.box > span.l-top, .box > span.l-bottom {
    border-top: 2px solid #b17b64;
    transform: scale(0, 1);
    transform-origin: left;
    transition-duration: .2s

.box > span.l-left, .box > span.l-right {
    border-left: 2px solid #b17b64;
    transform: scale(1, 0);
    transform-origin: top;
    transition-duration: .3s

.box > span.l-bottom {
    top: 48px;
    transition-delay: .5s

.box > span.l-right {
    left: 568px;
    transition-delay: .5s

.box:hover > span.l-top, .box:hover > span.l-left, 
.box:hover > span.l-bottom, .box:hover > span.l-right {
    opacity: 1;
    transform: scale(1, 1);

.box:hover > div > span.hover-me {
    left: -150px;
    opacity: 0;

.box:hover > div > span.hi {
    opacity: 1;
    left: 14px;

.box:hover > div > span.message {
    opacity: 1;
    left: 65px;
    transition-delay: .25s;
    transition-duration: .2s;

body > div.box:first-child:after {
    content: '\25bc';
    left: 47%;
    top: 50px;
    opacity: 0;
    transition: all .2s ease;

body > div.box:first-child:hover:after {
    opacity: 1;

.box:hover + div.box-next {
    opacity: 1;
    margin-top: 32px


That's all I have for this CSS episode. If you like what you see, do share it, and consider buying me a coffee to keep me juiced up for more JavaScript-free animations. Also, feel free to subscribe here, on devinduct, or follow me on twitter to keep up with the updates.

Thank you for reading and see you in the next article.