Text Rotation with CSS

Once again, after reading somebody else's article, I felt inspired to put together an alternative example. In this case: Text Rotation.

Within the article I linked to, the example uses an image sprite and a sprinkle of CSS to get things positioned right. Well, maybe not so much a sprinkle. It's like the top fell off the pepper shaker and you've suddenly got a large pile of pepper on your food. It makes me want to sneeze.

Thankfully, many of the popular browsers of today support the ability to rotate HTML elements. Even better? We can make it work in Internet Explorer (back to version 5.5 even). How you might ask? Okay, let's look at the HTML.

<div class="example-date">
  <span class="day">31</span> 
  <span class="month">July</span> 
  <span class="year">2009</span>
</div>

Nice and clean without too many extras. I conscientiously chose the date order I did to avoid having to use a comma. Otherwise, an extra span would be required to remove the comma from our final design.

The Magical CSS

For Webkit and Firefox (as of 3.5), you can take advantage of the proposed transform property to handle the rotation. Each browser requires its property prefix for now.

-webkit-transform: rotate(-90deg); 
-moz-transform: rotate(-90deg);	

In order to perform a transformation, the element has to be set to display:block. In this case, just add the declaration to the span that you want to rotate.

When it comes to effects in Internet Explorer, there is a surprising amount of power (and untapped at that, I'd say) in using filters. Although misleading, there is a filter called BasicImage that offers up the ability to rotate any element that has layout.

filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);

The rotation property of the BasicImage filter can accept one of four values: 0, 1, 2, or 3 which will rotate the element 0, 90, 180 or 270 degress respectively.

The BasicImage filter has other properties that can be set such as mirroring, masking, greyscale and others. Alternatively, you can take advantage of the Matrix filter but the coordinates still don't make any sense to me.

In action

31 July 2009

What does this look like in action? Take a look at this page in Safari, Firefox or Internet Explorer and you should see something that looks like the following image. Probably the biggest downfall is the lack of consistency in text rendering. Internet Explorer will drop ClearType on any text that has a filter applied to it. You can also see the spacing between the day and the year is different between Safari and Firefox. The differences in text rendering make it more difficult to create "pixel perfect" layout.

Here's hoping the article has offered up a little inspiration and shown that even IE has a few tricks up its sleeve, allowing us to pull off some layout fun.

Opera has -o-transform support in 10.50

Published July 28, 2009 · Updated April 01, 2010
Categorized as HTML and CSS
Short URL: https://snook.ca/s/952

Conversation

83 Comments · RSS feed
Divya said on July 28, 2009

Wow, this is awesome! Will be very useful!

Lakshan said on July 28, 2009

Thanks for posting this!

I remember I was struggling to do the same, several years ago - then it worked only in IE with basic image filter and didn't work on any other browsers.

nicksatkovich said on July 28, 2009

Awesome Article, very useful!!

Tom said on July 28, 2009

I'm literally stunned that this is possible in IE.

Beetbe said on July 28, 2009

This is useful
Tks @snookca

dave rupert said on July 28, 2009

ha. this is so awesome. i was just oooh-ing over Chris Coyer's tutorial from today (http://css-tricks.com/date-display-with-sprites/), but leave it up to Snook to come through with some old school BasicImage hacks! I hope squarespace pays you the big bucks.

Ollie Kavanagh said on July 28, 2009

I recently tried this with my personal vcard site (linked in my name) but had real trouble with IE turning off cleartype using rotate and opacity. The rendering ended up looking so bad I reverted back to images as you can see. And even then switching on opacity in IE on PNG images causes bad rendering.

We are destined never to have full support for this stuff :(

Henry B. said on July 28, 2009

I can't believe this is supported by IE 5.5... amazing. Thanks for the insight snook

Tyson said on July 28, 2009

Good post. Certainly opened my ignorantly closed eyes with regard to Internet Explorer. I will have to take a look more at some of those IE filters now. Thanks for sharing.

Kevin Thompson said on July 28, 2009

Ha! Perfect timing. I was just reading the css sprite article & considering implementing that concept for date formatting on a site I'm working on, but was too lazy to put together a sprite sheet. :) I'll give this a shot though.

David Rojas said on July 28, 2009

wow, that's great! I'm thinking of a lot of uses for that. It's not working in Opera though.

Adriaan said on July 28, 2009

Much better than the other site you linked to...thanks for explaining the proper way to do this.

Anthony said on July 28, 2009

I knew there was a reason I followed you on Twitter. A real gem, thanks ;)

Andrew Cornett said on July 28, 2009

Sweet, thanks a bunch Snook!

Jason Miller said on July 28, 2009

Awesome!

I would be interested in finding out where you came across the filter for IE. Is there a list available somewhere?

Korri said on July 28, 2009

It looks like it does not works on FF 3.5 debian

Jonathan Snook said on July 28, 2009

@Ollie: Agreed, it's unfortunate that it has to destroy ClearType just to apply an effect. It certainly means that you'd have to be more careful with your type choices to ensure a decent rendering for IE.

@David Rojas: Yeah, no Opera support as far as I know. I'm not sure if they plan to implement CSS transformations at any point.

@Korri: That's interesting that there are features that aren't available on that platform. That could be frustrating, that's for sure.

Jakob Heuser said on July 28, 2009

Given the -ms-filter extension in IE8 http://msdn.microsoft.com/en-us/library/ms533754%28VS.85%29.aspx I'd expect that there's probably a few other Visual Filters that can help bridge the CSS3 gaps such as DropShadow()*. It probably should go without saying that you should be careful about what you put filters on for performance reasons.

*Full Visual Filter reference at http://msdn.microsoft.com/en-us/library/ms532853%28VS.85%29.aspx

Chris Pratt said on July 28, 2009

Awesome article. I was literally just looking at the technique you alluded to this morning, but your approach here is so much nicer. Thanks alot.

9swords said on July 28, 2009

I was thinking about how to do this in a header menu last week with images, now i can start to develop without any!
Another breakthrough for web design. If the browser can understand javascript it should be able to do things like this with CSS transform. Including IE<- "The odd man out".
Thanks to you and Mr.Coyier for this.

Jason Beaird said on July 28, 2009

I link to an article I think is a good resource and then here comes Jonathan with a 1up on said article. No wonder you're winning the Happy Webbies contest so far. :)

Webmancers said on July 28, 2009

Well, the sprite thing is something we had to learn. But personally I'm not comfortable using a large stylesheet to define a big list of sprite coordinates for such a little thing. I'm much more interested in some more efficient ways to do so like the one I found at is.gd/1RgZU
It's pretty much a hack that will break CSS2.1 validation (who cares), but stay tuned to CSS3.

Webmancers said on July 28, 2009

Nevermind, I wanted to post this on other blog's comments Sorry. This is the efficient one

All for Design said on July 28, 2009

Waho...
Amazing possibilities...
Great article !

gWarez said on July 28, 2009

Not working here...

Windows 7 - Firefox 3.0.12
pic

Windows 7 - IE 8.0.7100.0
pic

Todd Smith-Salter said on July 28, 2009

That's a great solution for those who have images disabled. The solution on CSS-Tricks, while it looks great, pushed the text -1000em to the left.

Jonathan Snook said on July 28, 2009

@gWarez: Definitely won't work in Firefox 3.0. -moz-transform only got introduced in 3.5 (I mention this mid article but easy to miss). As for IE8 on Win7, my guess is that it needs the alternate syntax: -ms-filter and wrap the value in quotes. It was working on my version of IE8 so I didn't bother expanding on that approach.

Josh Smith said on July 28, 2009

I'm at a loss for words. I had no idea you could do something like this in IE 5.5. Great old school filter example, I love it!

Bookmarked your site for later. I'm going to have a peek around.

BOLK said on July 28, 2009

http://bolknote.ru/2006/12/16/~330

2006 year

Jasmin Halkić said on July 28, 2009

Nice article.

Janko said on July 28, 2009

I just read the article on css-tricks and I must say both ideas are interesting.

Jeff Nickel said on July 28, 2009

Excellent work. Will be very helpful in the future!

Christian said on July 28, 2009

I had written about this here: http://developer.cmzmedia.com/?p=368

Karl said on July 28, 2009

Yep, the clue was in the title of the other article (which I too read first), but your technique was the one that sprung to my mind. It wouldn't bother me about IE support although this is a bonus - definitely something from my progressive enhancement toolbox.

Aaron said on July 28, 2009

I was wondering about the possibility of rotating text with CSS. Found this page via twitter. Thanks for the write up!

EllisGL said on July 28, 2009

Doesn't work in FF 3.0.12 in XP 64 either.

Douglas Heriot said on July 28, 2009

I've been using rotate transformations on my new website’s contact form: http://douglasheriot.com/#contact

If you’re using a browser that supports it, there will be a “super fun fun button” at the bottom, which animates the contact form spinning around!

I haven’t made mine work in Internet Explorer yet though. It sounds like I would have to use the matrix transform filter, as I need more that 90° increments.

Carl said on July 28, 2009

This is BIG man, I mean designers will have a great time with this method.

Thanks!

C

Michael Kozakewich said on July 28, 2009

People have been beating up IE6, for not having this or that support, for so long that they can't believe it DOES have support for a wide range of effects. It's proprietary and confusing and from ten years ago, but it can help.

Myself, I've only tried some of the basics. There's a lot in there to see. I'll have to try more in the future, when I'm running into difficulties with the IEs.

Adel said on July 29, 2009

Thanks for sharing this!

Ashish said on July 29, 2009

A simpler and non-filter way to achieve vertical text in IE browser is the CSS property "writing-mode: tb-rl;" obeys clear-type in my test.
I think rotation of "text" is best handled by writing mode property as some languages also are written from top to bottom. Rotation however can be applied to DIVs; spans and such.
Last checked FireFox may support writing mode in future releases.

chris said on July 29, 2009

hey !
Thanks for this but it seems it doesn't work in opera browzer :(
any suggestions ?
Your website is really great !!

Kobi said on July 29, 2009

I'd also include the line

transform: rotate(-90deg);

Even if transform isn't official yet, some browsers may already support it (maybe Opera, they're usually the first with those sort of things), and one day all browsers will support it, like opacity today.

Webmancers said on July 29, 2009

Yes, I'll add the standard CSS3 properties to this (It probably won't change in the final TR), to ensure interoperability for CSS3 compliant browsers which need no specific layout engine hacks:

rotation: 90deg !important;
/* ** Hacks ** */
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);


Note that the default pivot point is

rotation-point: 50% 50%;

which should be just fine here (didn't tested).

Zach Leatherman said on July 29, 2009

Finally, we can do cross-browser horizontal accordion components without images!

Well, once Firefox 3.0 is at appropriately low levels of usage.

Morf said on July 29, 2009

Thanks for the article! Came in handy already :)

Rob said on July 29, 2009

Very cool, now I just need to get to work building an entire website sideways!

Colin Hardie said on July 29, 2009

Excellent post. Really clean approach and amazed that something like this can even work in IE! Not that I'll ever switch back from Firefox!

Jeffrey said on July 29, 2009

Not looking too great on IE 8 w/Vista. The 2009 appears to the right outside of the brown box.

Mike Badgley said on July 29, 2009

Hah, you must have been as bored as I was yesterday as I too felt inspired to try a different variation based on the same article you referenced.

You mentioned there being a whole pile of CSS needed when using sprites? True, but this variation takes care of that.

Pierre Paul Lefebvre said on July 29, 2009

That's kind of funny that Firefox is the one lacking behind.

joe larson said on July 29, 2009

I can't get any version of this working in IE8 (compatibility on and off), FF 3.5 and Chrome... Can anyone post a snippet of a 100% complete html that does this? Here is what I tested based on inspecting the html here:


<!DOCTYPE html>
<html>
<head>
<style type=text/css>
.example-date {
  background-color:#998877;
  float:right;
  margin-left:10px;
  padding:45px 5px 0;
  position:relative;
}
.example-date .example-day {
  font-size:45px;
  left:5px;
  line-height:45px;
  position:absolute;
  top:0;
}
.example-date .example-month {
  font-size:25px;
  text-transform:uppercase;
}
.example-date .example-year {
  -webkit-transform: rotate(-90deg);
  -moz-transform: rotate(-90deg);
  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
  display:block;
  position:absolute;
  right:-5px;
  top:15px;
}
</style>
</head>
<body>
<div class="example-date">
  <span class="day">31</span>
  <span class="month">July</span>
  <span class="year">2009</span>
</div>
</body>
</html>
 

joe larson said on July 29, 2009

@myself -- duh. in style block, replace ".example-month" with ".month", ".example-day" with ".day", ".example-year" with ".year".


<!DOCTYPE html>
<html>
<head>
<style type="text/css">
.example-date {
  background-color:#998877;
  float:right;
  margin-left:10px;
  padding:45px 5px 0;
  position:relative;
}
.example-date .day {
  font-size:45px;
  left:5px;
  line-height:45px;
  position:absolute;
  top:0;
}
.example-date .month {
  font-size:25px;
  text-transform:uppercase;
}
.example-date .year {
  -webkit-transform: rotate(-90deg);
  -moz-transform: rotate(-90deg);
  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
  display:block;
  position:absolute;
  right:-5px;
  top:15px;
}
</style>
</head>
<body>
<div class="example-date">
  <span class="day">31</span>
  <span class="month">July</span>
  <span class="year">2009</span>
</div>
</body>
</html>

Ryan Corradini said on July 29, 2009

Ashish: your suggestion of using the writing-mode property appeals to me, but note that it won't exactly yield the same results in this particular case because it causes the year text to be rotated in the wrong direction (+90 degrees instead of -90 degrees)

Will Peavy said on July 29, 2009

Use

-ms-filter: ...

to add support for IE8 Standards mode

Scott C. Hughes said on July 29, 2009

Jonathan,
Good writeup. Thanks for the article.

You can get the text of the filtered element to clean up if you give the element a background color. For example: background-color:#998877; It's a fix that cleans up most filter display issues.

I also found that explicitly setting the font size on the element to font-size:1.1em; gives a more consistent size across browsers. It may take a little css filtering to get a constant position though. :-)

Below is joe larson's version with my changes. Enjoy!

Again, thanks for the writeup Jonathan.

<!DOCTYPE html>
<html>
<head>
<style type="text/css">
.example-date {
  background-color:#998877;
  float:right;
  margin-left:10px;
  padding:45px 5px 0;
  position:relative;
}
.example-date .day {
  font-size:45px;
  left:5px;
  line-height:45px;
  position:absolute;
  top:0;
}
.example-date .month {
  font-size:25px;
  text-transform:uppercase;
}
.example-date .year {
  -webkit-transform: rotate(-90deg);
  -moz-transform: rotate(-90deg);
  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
  display:block;
  font-size:1.1em;
  background-color:#998877;
  position:absolute;
  right:0px;
  top:10px;
}
</style>
</head>
<body>
<div class="example-date">
  <span class="day">31</span>
  <span class="month">July</span>
  <span class="year">2009</span>
</div>
</body>
</html>
John Dowdell said on July 29, 2009

Rotation was introduced in Internet Explorer 4, with the nicer "flip" syntax:
http://msdn.microsoft.com/en-us/library/ms532847(VS.85).aspx
http://web.archive.org/web/19980201041517/www.dhtmlzone.com/articles/dhtmloverview.html

But this was a situation where only some developers designed for such a subset of browser, and where audience members rebelled at the "Works Best in Browser X" tag.

The above syntax is already verbose, but will require another clause once this behavior is standardized.

I know some folks online have a religious objection to Flash, but when you stop to think things through....

jd/adobe

Subin Idic said on July 30, 2009

Snook, Is there any fix for the same in mozilla browsers?

Amazed to see its working IE6!!!

Thanks
Subin

Alex said on July 30, 2009

Doesn't work - Mac 10.4.11 Firefox 3.0.12

Skoua said on July 30, 2009

Nice trick, too bad this doesn't validate at all for now.

Splat said on July 30, 2009

In IE7 (I haven't tested others), it looks like the trick of adding a background colour to the .example-year seems to fix up the ClearType issue:


<!--[if IE]>
<style>
.example-date .example-year {
  background-color:#987;
  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
  right:-15px; top:5px;
  }
</style>
<![endif]-->

Could something similar be achieved in IE using -ms-writing-mode without using a filter?


.example-date .example-year {
  -ms-writing-mode:tb-rl;
  writing-mode:tb-rl;
  }

More info about -ms-writing-mode : http://msdn.microsoft.com/en-us/library/ms531187(VS.85).aspx

tylor said on July 31, 2009

search the google then find your site.
that is a really excellent post.

Thanks for the post.

Will said on July 31, 2009

Nice tip, it works fine in IE6 but unfortunately the 2009 is not slanted in FireFox version 3.0.12

Joel Drapper said on July 31, 2009

Wow! I had no idea you could do that!

Thanks for posting about it. I'll be sure to consider this in my next design.

Uday Sutaria said on July 31, 2009

really this is dream comes true.
I was searching for this kindo code since long.
Thanks very much.
Keep going.

Ain Tohvri said on August 01, 2009

Nice cross-browser overview.

As for the WebKit, this functionality has been there for quite some time now. I blogged about CSS transitions 2 years. You can basically animate the whole rotation in conjunction with CSS transforms (test-cases only work in WebKit).

Let's hope it will soon leave the Working Draft of W3C and we'll get to use these properties in an uniform way.

Sam Vloeberghs said on August 01, 2009

Very nice tip! I will use it in my next blog design ;)

Thx
Keep up the nice articles

Ben Schwarz said on August 04, 2009

While you're at it Jonathon, maybe you could use the

<time>

tags and experiment with HTML5?

Ben Schwarz said on August 04, 2009

Typo on your name there, my bad :)

Tom Bradshaw said on August 12, 2009

Awesome article, cheers!

Swapnil said on August 13, 2009

Very nicely written. This is cool stuff!

Nathan Nash said on August 13, 2009

Wow this is a power bit of code:

-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);

I need something just like this for the realigning i'm doing right now.

Nicole Sullivan said on August 14, 2009

It is amazing how much of the stuff we are seeing in CSS recently was done by Microsoft via proprietary filters years back. Great article.

Thanks, Nicole

Rajagopalan said on August 20, 2009

The above code works fine.. but it is not getting displayed in Firefox 3.0. can u please help me out.. Please it's urgent.

Thanks
Rajagopalan

Bruce Bell-Myers said on February 03, 2011

I wonder if you have looked into IE 9. Does it have these same issues with antialiasing going haywire when rotated?

Jonathan Snook said on February 03, 2011

@Bruce: IE9 supports -ms-transform which provides finer control over the rotation and the rendering is probably one of the better text renderings cross-browser.

Ashok vardhan said on February 05, 2011

nice article Mr.jonathan , thanks for sharing .

Gray said on February 07, 2011

Great article!
Opera still is not supporting this, even the latest version 11.01 - very sad.

CarlGY said on February 19, 2011

Will the north star (polaris) always be the north star?

Chris Harrison said on February 25, 2011

I found a solution for Opera!

You have to use a wildcard on everything within a container in order for -o-transform to work. Example:


#container * {
-o-transform: rotate(270deg) !important;
-o-transform-origin: 50% 50%;
}

As opposed to:


#verticaltext {
-o-transform: rotate(270deg) !important;
-o-transform-origin: 50% 50%;
}

(which will do nothing...)

Vimal Patel said on March 29, 2011

Hi,
works great where span tag could be use.
<li><a href="#" id="issuesBI" runat="server" title=""><span>issues</span></a></li>

could I use it for rotating text in buttons ??

how could I rotate submit text in follow button code??
<li><input type="submit" name="submitButton" value="submit" onclick="return SubmitBI_Check();" id="submitButtonBI" /></li>

not able to use span tag in button/input tag :-(

Thanks in Advance

Jonathan Snook said on March 29, 2011

@Vimal: There's a couple options. One, best to rotate things that would normally be a block element. Rotating just the span in an anchor may be problematic. Rotating the anchor or the li may be better, depending on your design. However, you can do <button><span></span></button>.

BHB said on April 27, 2011

Thx, worx great

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.