Try Tuts+ Premium, Get Cash Back!
The Easiest Way to Create Vertical Text with CSS
videos

The Easiest Way to Create Vertical Text with CSS

Tutorial Details
  • Topic: CSS Vertical Text
  • Difficulty: Easy
  • Format: Written + Video

Earlier this morning, I needed to create vertical text for a project I’m working on. After trying out a couple 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!

*Note – please refer to “Method 6″ below for more details about proper usage.

Subscribe to our YouTube page to watch all of the video tutorials!
Prefer to watch this video on Screenr?


Method 1: <br> Tags

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

<h1>
   N <br />E <br />T <br />T <br />U <br />T <br />S
</h1>
View a Demo

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.

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Vertical Text</title>

<style>
  h1 span { display: block; }
</style>
</head>
<body>
 
  <h1>
   <span> N </span>
   <span> E </span>
   <span> T </span>
   <span> T </span>
   <span> U </span>
   <span> T </span>
   <span> S </span>
  </h1>
  
</body>
</html>
View Demo

The problem with this solution — other than the frightening mark-up — 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.

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>

<style>
  h1 span { display: block; }
</style>
</head>
<body>
  <h1> NETTUTS </h1>
  
  <script>
    var h1 = document.getElementsByTagName('h1')[0];
    h1.innerHTML = '<span>' + h1.innerHTML.split('').join('</span><span>') + '</span>';
  </script>
</body>
</html>
View Demo

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.

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

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.

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>

<style>
  h1 {
    width: 50px;
    font-size: 50px;
    word-wrap: break-word;
  }
</style>
</head>
<body>
  <h1> NETTUTS </h1>
</body>
</html>
View Demo

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.

Broken Again

Yikes; with this method, we have to be very careful when it comes to the specific values we set. Not recommended.


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?

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>

<style>
  h1 {
    width: 50px;
    font-size: 50px;
    word-wrap: break-word;
    letter-spacing: 20px; /* Set large letter-spacing as precaution */
  }
</style>
</head>
<body>
  <h1> Nettuts </h1>
</body>
</html>
View Demo

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


Method 6: Use ems

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 ems, and place a space between each letter.

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>

<style>
  h1 {
    width: 1em;
    font-size: 40px;
    letter-spacing: 40px; /* arbitrarily large letter-spacing for safety */
  }
</style>
</head>
<body>
  <h1> N e t t u t s </h1>
</body>
</html>
View Demo

Pretty neat, right? And, this way, you can apply any font size that you wish. Because we’re using ems — 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.

To my knowledge at this time, this is the best, most cross-browser compliant solution.


Method 7 : Whitespace

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

<!DOCTYPE HTML>
<html lang="en">
   <head>
      <meta charset="UTF-8">
      <title></title>
      <style>
         h1 { white-space: pre; }
      </style>
   </head>
   <body>

      <h1>
         J 
         E 
         F 
         F 
         R 
         E 
         Y
      </h1>
   </body>
</html>
View Demo

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


Conclusion

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?

What do you think? Do you have any other alternatives that we should consider? Many people suggested using text-rotation to accomplish the task, but it’s important to remember that this also rotates the text ninety degrees as well, which is not what we’re trying to achieve.

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://www.centerdrive.ca Todd Smith-Salter

    Interesting post! My question is, in what practical setting would this be used? Can vertical text be used in a readable design? My first thought is that obviously, this technique would only be used for headers/titles/etc. I’d be interested to see any examples of this in practice.

  • http://twitter.com/immysl immysl

    I might need this when building sites for the Chinese or Japanese? :-/ Anyway that’s a cool way to experiment. :) Thanks for this nice post.

    • http://twitter.com/scriptin Dmitry Scriptin

      it would be nice to have something like this:
      direction: ttb; /* top-to-bottom*/

  • http://tj.abderrahmane.com Abderrahmane TJ

    “Vertical Text with CSS ” !?

    you’re using JavaScript :D to split the text for you. and it’s not really Vertical :P I was wating to see a sort of 90° rotation.

    but kinda clever tip, thanks.

    • http://www.jeffrey-way.com Jeffrey Way
      Author

      Looks like you didn’t read the whole article. :)

      • http://davidbecerra.com David B.

        Shaaaaaame!!! lol

      • http://tj.abderrahmane.com Abderrahmane TJ

        YaaaY Touché :D

        I usually don’t read the hole article. First the titles then if i feel like i have to read details i do. so this time you’ve got me there :D

    • http://www.pixelsoul.com pixelsoul

      This is what you want for actually rotating the text. Works in all major browsers.

      -moz-transform:rotate(-270deg);
      -moz-transform-origin: bottom left;
      -webkit-transform: rotate(-270deg);
      -webkit-transform-origin: bottom left;
      -o-transform: rotate(-270deg);
      -o-transform-origin: bottom left;
      filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);

      • Rahul Hanchinamane

        I agree with pixel soul.. I recently experimented with vertically aligned elements..

        The transform property is the most easiest and the first method I used.

      • http://www.jeffrey-way.com Jeffrey Way
        Author

        The two problems being that it doesn’t work in all browsers, and that we’re not trying to rotate text sideways in this particular case.

      • Matt27

        could this technique not be used with a font that has letters rotated at a 90 degree angle (not sure if such a font exisits, but wouldn’t be hard to make).

      • http://tj.abderrahmane.com Abderrahmane TJ

        Yeah that’s what i was talking about. thanks though

    • Michael

      when i read the heatline, i thought about 90/-270 degree rotation, too, and not “one letter per row”.
      but maybe i netd you solutions sometimes, thx.

  • http://twitter.com/scriptin Dmitry Scriptin

    I got pure CSS method, w/o extra markup and JS. It based on multiple text-shadow + letter-spacing + overflow:hidden

    http://pastebin.com/D8TNaWF0

    But it’s typeface-dependent :(

    • http://twitter.com/scriptin Dmitry Scriptin

      Actually, it is more then just typeface-dependent. It is also CSS3- and font-size-dependent and requires manual adjusting to work well.

  • http://www.pixelsoul.com pixelsoul

    I like the one using span or just javascript. You were right, I laughed at the different ways of doing this. I do agree we should have a letter-display in css.

  • Robert

    This is pretty cool trick. I’m just wondering, it doesn’t seem like you can adjust the space between the letters. What if you wanted more or less space between each letter vertically ?

    • http://twitter.com/scriptin Dmitry Scriptin

      Just use line-height

      • Robert

        *smacks forehead* yeah, I should have thought about that. Thanks.

  • Andre Dublin

    Neat, I thought that text-transform would accomplish this, but that only rotates the text, not realign the letters to read top to bottom.

  • http://joshcaza.com Joshua Chase

    Holy EPIC tutorial Batman. This is fantastic. I will be trying this out this weekend. Thoroughly impressed with the attention to detail and the step by step instructions!

    Now.. where is my delicious bookmark button…

  • http://www.pushinpixels.co.uk Paul909of9

    Adobe support vertical text in their Text Layout Framework (TLF), just need the Browsers support now.

  • http://designlovr.com ximi

    Nice to see so many different approaches to the same problem. Rather then a letter-display property I would rather propose a text-orientation (horizontal, vertical, diagonal?) property or an extension of the already existing direction property.

  • Arthur Corenzan

    As I said earlier on Twitter, we can use regex to make the transformation – http://jsbin.com/ugawi3

    • http://www.jeffrey-way.com Jeffrey Way
      Author

      Hey Arthur,

      Right – but you’re still using a for statement to filter through the array. Easier (if you’re using JS) to use the split + join method I showed above.

      • http://michael.theirwinfamily.net Michael

        … and it’s still Javascript dependent.

  • Napoleon

    Very cool tip! BTW Jeffery what is the theme are you using for Vim? If its custom like you did for netbeans, do you mind sharing it?

  • http://elamperti.com/ Zim

    Anyhow, be careful. A designer could stab you if he finds out you’re using vertical text! They recommend to use text rotated 90°, or 270°; always in a line. It’s easier to read!

  • Juan

    WOW, what about the “pre” tag??

    http://jsbin.com/ovoxa3/2

    • http://www.jeffrey-way.com Jeffrey Way
      Author

      Hey Juan – Good idea. Even better, we can use the white-space property set to “pre.” I’ll update the posting!

    • http://designlovr.com ximi

      That’s an excellent idea! Great thinking

  • http://www.how-to-asp.net Ryan

    These are some really great ideas, I’ve never had a scenario where I needed to do this sort of thing. There really isn’t a good way to do it either. Thanks for sharing everyones ideas!

  • http://michael.theirwinfamily.net Michael

    When you showed the CSS declaration, I literally yelled out, “WHAT?!?”. Haha… I couldn’t believe it was so simple.

    I also have to admit it was funny how often you used “stupid” and “lame”. Thanks for the post!

    • http://www.jeffrey-way.com Jeffrey Way
      Author

      Every time I say the word “lame” now, I think of that episode of Family Guy where Stewie goes to high school.

  • http://rickysalsberry.com Ricky Salsberry

    Anyone who knows a lick about typography knows you never, ever, stack text like this.

    Sad to see this tutorial encouraging bad typography.

    • http://www.jeffrey-way.com Jeffrey Way
      Author

      That’s ridiculous. It entirely depends on the project. If you’re handed a design that requires top-to-bottom text, then you’ll need to know the easiest way to do it.

    • Jo

      Anyone who knows a lick about life, knows you never ever make such inane statements

  • w1sh

    Thought of the solution while I was watching it. Can’t think of anything simpler/cleaner, so it seems like you’ve won this round Jeffrey Way.

    …next time…

    • w1sh

      Oh nevermind. You can erase those spaces to get your H1 SEO value back.
      Best solution -> http://jsbin.com/ahomu4/2

      • w1sh

        And I really don’t think Guillaume stole my bright idea or anything. I knew it’d be a successful tut and was wondering why it was rejected for that bottom of the barrel stuff that was getting posted.

        “In all honesty, when you’re repeatedly disrespectful to other within the comments, it does not make us want to post your tutorials. That’s why your submission was rejected.”

        But now I know.

  • http://mokshasolutions.com Moksha

    its really that simple,

    I used jquery but this way its cool

  • http://valid-webs.com Jeff

    p {
    text-transform: uppercase;
    width: 50px;
    font-size: 50px;
    word-wrap: break-word;
    }

    Works fine for me in FF3, Safari, Chrome, IE8, and in IE Tester IE6 and IE7 also.

    • w1sh

      What if someone wants lower case?
      Forget the text transform and use letter-spacing: 100em;
      Haven’t browser tested but I think if it does break you could just set h1 { overflow:hidden; } and it’d work.

      And set width: 1em;

  • http://jvdesigns.com.au Jason

    I haven’t read the whole post or all of the comments. Just jumped right down to the comment box, so excuse me if I’m repeating something here, but you could use Lettering.js

    http://daverupert.com/2010/09/lettering-js/

    Perhaps overkill for one word, but still…

    • w1sh

      Why make something JS dependent when it’s so easily done with CSS?

      • http://designlovr.com ximi

        Agreed! People nowadays tend to use javascript for every styling problem they encounter. Javascript mainly exists to add a (non-essential) behavioral layer to a site, not to make its basic looks work.

  • http://www.buzzednow.com Buzzednow

    hmm, its kinda simple, don’t know yet if i can use this technique in my site though

  • http://zoftpc.com zoftpc

    great tutor, i must read again and again.. css make me headache :)

  • http://www.sparsh-technologies.com/ Sparsh

    I know first two methods to create vertical text. but other methods are new for me. i have never tried to use javascript for that.

  • aufula

    I prefer to use letter-spacing to keep each single letters bigger than its container ;

    because i can control both container’s width(for float and) and font-size;

    h1{
    width:20px;
    font-size:15px;
    letter-spacing:999em; // lol ,it seems like text-indent:-999em;
    word-wrap:break-word;
    float:left;
    }

    This Line one
    This Line two
    This Line three

  • Karl Ballard

    The best way I can think of is using:
    h1 {
    width: 1px;
    font-size: 3em;
    word-wrap: break-word;
    }

    However, I admit, like most of the others.. It’s CSS3 Dependent

    Demo: http://jsbin.com/epihu3/2

  • http://enrique-ramirez.com Enrique Ramírez

    Quick note: letter-spacing is NOT CSS3. It is CSS 2.1. :) This should work pretty neately:

    h1 {
    width: 1em;
    font-size: 40px;
    letter-spacing: 2em;
    }

    • http://enrique-ramirez.com enrique

      D’oh… I just realized you were talking about word-wrap rather than letter-spacing. :P Regardless, the above code is pure CSS2.1 and should work on all and any browser you throw it to. Adding word-wrap should just make it even more bulletproof.

  • http://jason.karns.name Jason

    Why not take method #6 and add word-wrap:break-word? Then you can eliminate the spacing between each letter. (which doesn’t work when the text is dynamic)

    Also, the letter-spacing doesn’t need to be arbitrarily large. It only needs to be as wide as the container. 1em is much nicer.

    And last note, throw in a non-breaking-space if you need to separate words.

    h1 {
    width: 1em;
    font-size: 40px;
    letter-spacing: 1em;
    word-wrap: break-word;
    }

    http://jsfiddle.net/jasonkarns/cHH6D/

    (Tested in IE7/8, Firefox, Chrome)

  • Derek Stegelman

    Using break tags for this is not lame or sloppy.

    The javascript method is fine, but there are many users out there that do not have javascript enabled on their browsers. Having said that, you may be fine with it breaking in that situation. But in my opinion if there is any easy way to achieve this with HTML, why the hell would you use javascript to do the same thing? From a UX perspective using javascript to achieve this is wrong in my opinion.

    • http://www.jeffrey-way.com Jeffrey Way
      Author

      And I agree with you 100% on using JS. But I do think adding a bunch of br tags is sloppy…not to mention impossible, when working with a CMS.

  • http://www.impressivewebs.com Louis

    Hey, Jeffrey, interesting solutions presented here.

    One thing I wanted to point out is that, although word-wrap is technicaly a CSS3 property, it’s a pretty old one, and has very good browser support (FF 3.1+, IE6+, Opera, Chrome and Safari — though I’m not sure the versions for those last three, but I assume it’s pretty good).

    Thus, I think method #4 or #5 would be the best options, because the text in the markup can remain standard without any extra spaces, and there is no JavaScript necessary.

    • http://www.jeffrey-way.com Jeffrey Way
      Author

      Yep – good point.

  • Bruce Salem

    I may be asking a dumb newbie question, but how do you do the real world task of doing the “neon sign” with some normal article just to its right? I tried to do this and the article appeared below the vertical header
    not to its right. All of the examples showed the heading with no other interacting elements.

    • B

      I was able to get articles to flow to the right of the sign in what I judge to be a real world example, but the effort may not be worth the value of the hack being proposed here. I had to use “position: absolute;”
      and a different top position in ems for each article on the page. That seems like more work than it should be unless someone can suggest a better style setting to get the articles to flow in one after the other like you might expect..

  • nXqd

    Thanks for your great post as always ;)

  • Ayo

    Thanks a lot, I was educated.

  • carlos

    That is an easy effect to do. I do that on accident sometimes. You get paid to write something like this? Man, I need to start signing up for this stuff.

    Jeffrey, I love your tutorials and you do a ton of great ones but man I really want to start doing these if it is that easy.

    Thanks.

    • carlos

      I mean I need to sign up to make a few tutorials of some easy CSS, JS stuff. if it is that easy.

  • http://www.duy-tran.de Duy

    I like it THX ;)

  • http://www.twizzlebird.co.uk dave wright

    I too thought this was going to be on rotation, still some cool tips. Thanks

  • http://elementdesignllc.com Chad Huntley

    Using break tags is not only sloppy, but it is not accessible to users using screen readers. All of the other methods will read the word in full, however by using breaks it would read it letter by letter.

  • Bruce Salem

    The solution to this is to put all the articles in one container and style that with the position override. Don’t absolute position the articles individually, use the container to encapsulate all of them to flow
    in an orderly fashion, one after the other.

  • Ciwan

    Awesome, Thank you.

  • Abhinash

    Thanks it is helpful.

    :)

  • http://www.mindfiresolutions.com Deviprasad Das

    You can change layout of your text by using the text layout property -”writing-mode”.
    For example, to make text vertical you can add the following code –

    writing-mode: tb-rl;

    Unfortunately, as of yet, only Internet Explorer supports it, to get the
    same result in other browsers you have to rotate text in the following
    manner.

    For Firefox: -moz-transform: rotate(90deg);
    For Opera: -o-transform: rotate(90deg);
    For Safari and Chrome : -webkit-transform: rotate(90deg);

    But the good news is, */writing-mode/* property is already included in
    CSS draft specification.

    which implies that in near future more browsers, especially the popular ones will support it. And it’s not just top-to-bottom text layout, writing-mode property supports other layouts too. In the above example “*writing-mode: tb-rl*” instructs browser to display text flow /top-to-bottom/, /right-to-left. /To display text from bottom-to-top and left-to-right you can use the value *bt-lr*. You can find all possible
    writing-mode properties here

    Source: http://www.mindfiresolutions.com/How-to-rotate-text-using-CSS-properties-964.php

    Thanks.

  • Mike

    Thanks for showing your thought process to solve this problem.

    I can see why method #2 is unacceptable for dynamic content, but the same criticism holds for methods 6 and 7, right?

  • Marc

    nice short tip! ever when i need something to know.
    http://www.net.tutsplus.com helps me :D
    thx

  • Alexandra

    Hello nice work as always!

    How can I create a text rotate 45 degrees in CSS3 is this possible?
    I only found 90 degrees with rotate.
    Any suggestions?
    Thanks

  • Rylie

    This is unrelated (sorry). I just watched your video above and noticed that you were using MacVim, and it was doing code hinting for you! How did you get MacVim to do code hinting/completion?

  • http://wordpress-tech.info/ Wordpress Tut

    Wow!
    usefull.
    Thanks guys!

  • BT

    From a design standpoint, vertical text is usually considered a no-no, if only because the typeface was not designed for this sort of implementation, and therefore looks awkward (in my opinion anyways). Then again, part of the fun as a designer is making bastardizations work. From the perspective of one who is trying to find the cleanest, most semantic way to approach this particular problem, I’m glad to see some differing clever approaches. Interesting article.

    • Leonardo Pereira

      From my design standpoint, it would be interesting to display certain kinds information as vertical text. Such as furigana.

  • http://bb aaa

    oh yes

  • http://www.john-max.com John Max

    Nice tutorial. Thanks….

  • Matt

    Unfortunately, the only method here that will permit the proper usage of text-align: center; is Method 1. Otherwise, all letters are completely left justified. Any way around this?