Advertisement
  1. Web Design
  2. HTML/CSS
  3. CSS

The Easiest Way to Create Vertical Text With CSS

Scroll to top

Earlier this morning, I needed to create vertical text for a project I'm working on. After trying out a couple of ideas, I took to Twitter to find what sorts of thoughts our followers had on the subject. There were plenty of great responses and ideas that we'll go over today!

Method 1: <br> Tags

One possible (though not recommended) way to achieve vertical text is to add <br> tags after each letter.

1
<h1>
2
   V <br />E <br />R <br />T <br />I <br />C <br />A <br />L
3
</h1>

Don't use this method. It's lame and sloppy.

Method 2: Static Wrapping

With this method, we wrap each letter in a span, and then set its display to block within our CSS.

1
<!DOCTYPE html>
2
<html>
3
<head>
4
<meta charset=utf-8 />
5
<title>Vertical Text</title>
6
 
7
<style>
8
  h1 span { display: block; }
9
</style>
10
</head>
11
<body>
12
  
13
  <h1>
14
   <span> V </span>
15
   <span> E </span>
16
   <span> R </span>
17
   <span> T </span>
18
   <span> I </span>
19
   <span> C </span>
20
   <span> A </span>
21
   <span> L </span>
22
  </h1>
23
   
24
</body>
25
</html>

The problem with this solution—other than the frightening markup—is that it's a manual process. If the text is generated dynamically from a CMS, you're out of luck. Don't use this method.

Method 3: Use JavaScript

My initial instinct was to dynamically add the span tags with JavaScript. That way, we get around the issues mentioned in method two.

1
<!DOCTYPE html>
2
<html>
3
<head>
4
<meta charset=utf-8 />
5
<title>JS Bin</title>
6
 
7
<style>
8
  h1 span { display: block; }
9
</style>
10
</head>
11
<body>
12
  <h1> VERTICAL </h1>
13
   
14
  <script>
15
    var h1 = document.getElementsByTagName('h1')[0];
16
    h1.innerHTML = '<span>' + h1.innerHTML.split('').join('</span><span>') + '</span>';
17
  </script>
18
</body>
19
</html>

This method is definitely an improvement. Above, we split the text into an array, and then wrap each letter in a span. While we could use something like a for statement or $.map to filter through the array, a far better and quicker solution is to manually join and wrap the text at the same time.

Though better, this solution isn't recommended. Here are two reasons:

  1. Will this break your layout if JavaScript is disabled?
  2. Ideally, we should be using CSS for this task.

Method 4: Apply a Width to the Container

Let's get away from JavaScript if we can. What if we applied a width to the container element and forced the text to wrap? That could work.

1
<!DOCTYPE html>
2
<html>
3
<head>
4
<meta charset=utf-8 />
5
<title>JS Bin</title>
6
 
7
<style>
8
  h1 {
9
    width: 50px;
10
    font-size: 50px;
11
    word-wrap: break-word;
12
  }
13
</style>
14
</head>
15
<body>
16
  <h1> VERTICAL </h1>
17
</body>
18
</html>

In this scenario, we apply a very narrow width to the h1 tag, and then make its font-size equal to that exact value. Finally, by setting word-wrap equal to break-word, we can force each letter onto its own line. However, word-wrap: break-word is part of the CSS3 specification and is not compliant across all browsers.

Excluding older browsers, this seemingly solves our problem... but not entirely. The demo above does appear to work, but it's too risky to play with pixel values. Let's try something as simple as turning the uppercase letters into lowercase.

Method 5: Apply letter-spacing

As a precaution, and to extend method four, why don't we apply fairly large letter-spacing to get around this issue?

1
<!DOCTYPE html>
2
<html>
3
<head>
4
<meta charset=utf-8 />
5
<title>JS Bin</title>
6
 
7
<style>
8
  h1 {
9
    width: 50px;
10
    font-size: 50px;
11
    word-wrap: break-word;
12
    letter-spacing: 20px; /* Set large letter-spacing as precaution */
13
  }
14
</style>
15
</head>
16
<body>
17
  <h1> VERTICAL </h1>
18
</body>
19
</html>

That seems to fix the issue, though, again, we're using a bit of CSS3 here.

Method 6: Use em

Alternatively, there's a one-liner solution. Remember when we learned that applying overflow: hidden to a parent element would miraculously make it contain its floats? This method is sort of like that! The key is to use em and place a space between each letter.

1
<!DOCTYPE html>
2
<html>
3
<head>
4
<meta charset=utf-8 />
5
<title>JS Bin</title>
6
 
7
<style>
8
  h1 {
9
    width: 1em;
10
    font-size: 40px;
11
    letter-spacing: 40px; /* arbitrarily large letter-spacing for safety */
12
  }
13
</style>
14
</head>
15
<body>
16
  <h1> V E R T I C A L </h1>
17
</body>
18
</html>

Pretty neat, right? And, this way, you can apply any font size that you wish. Because we're using em—which is equal to the x-height of the chosen font—we're then provided with a lot more flexibility.

But, once again, sometimes more than one letter will end up on a line. You have to be safe; that's why I've applied arbitrarily large letter-spacing to ensure that there's never more than one letter on a line.

Method 7: Whitespace

One last way to achieve this effect is to take advantage of the white-space property.

1
<!DOCTYPE HTML>
2
<html lang="en">
3
   <head>
4
      <meta charset="UTF-8">
5
      <title></title>
6
      <style>
7
         h1 { white-space: pre; }
8
      </style>
9
   </head>
10
   <body>
11
 
12
      <h1>
13
         V
14
         E
15
         R
16
         T
17
         I
18
         C
19
         A
20
         L
21
      </h1>
22
   </body>
23
</html>

By setting white-space to pre, that instructs the text to behave as if it was within a pre tag. As such, it honours any spacing that you've added.

Method 8: Using writing-mode

Our next method is one of the newest in town. We have a property called writing-mode in CSS to help us write vertical text. 

Pairing writing-mode and text-orientation will help you achieve this goal. What writing-mode does is change the direction in which the text is written. You can change the direction from horizontal, top to bottom (well, this is the default option for writing-mode) to vertical right to left or vertical left to right. This is how simple the whole writing direction gets. You need to be careful if the application might be seen in ancient browsers because the property is unavailable in older browsers. If you want writing-mode to work in older browsers, add the following:

  • Horizontal top-to-bottom: writing-mode: lr
  • Vertical right-to-left: writing-mode: tb-rl
  • Vertical top-to-bottom: writing-mode: tb-lr

Next, we choose to change the direction of the characters. This is where the text-orientation property becomes useful. There are three options to choose from: mixed, upright, and sideways, where mixed is the default setting. 

Method 9: Using Transform

Finally, let's deal with a funky alternative if all of the above modern-browser compatible solutions fail. If writing-mode does not work for some reason, you can leverage the transform: rotate(90deg) property. This will rotate the text in a clockwise direction. Of course, if you want the text to be rotated in the other direction, make it rotate(-90deg). 

Undeniably, this method is extremely inconvenient. You certainly have all the other options to vertically turn text.

Conclusion

There were days when developers pondered, "Shouldn't there be a CSS3 rule to accomplish this task?" What if I could set something along the lines of font-display: letter-block; which would instruct each letter to be rendered as a block of sorts? Well, now you have options like writing-mode and text-orientation to achieve vertical text.

This post has been updated with contributions from Divya Dev. Divya is a front-end developer more than half a decade of experience. She is a grad and gold medalist from Anna University.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.