Using Nice Fonts for Headlines

22 comments | Posted: 8 August 06 in Tutorials, by Andy Knight

Sometimes I envy print designers. They have complete control over what the end user sees. They don’t have to worry about browser inconsistencies. They don’t fret over whether someone might come along and resize the text of their magazine article. They need not wonder if someone reading a book will have their styles or their javascript turned off. And the part I envy the most: They can choose any font they want. Web designers get to choose any font they want, as long as it’s Times New Roman, Verdana, Arial, Courier, or Georgia. Those lucky print designers must have a cushy life.

Or do they? Haggling with printers. Getting in their car to go to a press check. The high cost of paper. Paying more to get to use every color. Yes, there are trade offs in every profession. Hmmm. I think I’ll stick with web design.

And in the web design world, we live in a world of trade offs, particularly when it comes to fonts. The problem is that you are limited to using only fonts that are installed on the end user’s computer. You might be able to see that fancy Trajan Pro font on your computer, but their computer might substitute Times New Roman.

If we want to use the latest cool font, we have to build it into an image. Okay, that’s not really that hard, unless it’s text that you have to change a lot. Then you have to redesign that image in Photoshop every single time you want to change it. That’s serious trade off. Do we go for the cool factor or the flexible factor?

Can we do both? Is it possible to use fonts in your design that are both flexible and cool?

There have been other methods of displaying dynamic text in the past. I’m familiar with sIFR that uses Flash to dynamically change out the text, and I hear that’s a really good choice. I want to offer you another option. I’m not saying that mine is the best. It’s just an idea that came to me, and it may not even be original. Just because I’ve never run across anything like it, doesn’t mean that you haven’t. There have probably been others who have done something like it.

I call this the vTIM, or Very Tall Image Method :-) You’ll see in a little while why I call it this. First, take a look at the demo

Let’s say you have text on your website, perhaps an article headline, that is generated dynamically, probably pulled from a database. You want to style these titles in a unique font, but you don’t want to open Photoshop and create a new image for each one. Here is what you do:

First, split the headline

I used a PHP function called preg_split to separate each letter of the headline into an array. If your server is equipped with PHP5 or greater, than you can use str_split, which is simpler does not utilize regular expressions like preg_split does. Since my host has not yet upgraded to PHP5, I’ll stick with preg_split.

Then I use a “for loop” to loop through each letter and wrap it with an HTML <span> tag. While doing that, I also give the span tag a special class based on the letter of the alphabet, so I can target each letter separately using CSS.

For instance, my headline…


Would become…

<span class="letter_T">T</span>
<span class="letter_i">i</span>
<span class="letter_m">m</span>
<span class="letter_e">e</span>

You might want to download the PHP script (.txt)

Next, create an image

Create one image that contains every letter of the alphabet (uppercase, lowercase, numbers, punctuation, and other special characters). My image looks like this. I used the classic looking Trajan Pro. I also used set the line height in Photoshop to 25px. This nice round number will make life a little easier for me down the road when I start building out the CSS. You can download my Photoshop source file (.psd) to get you started.

Now, setup the CSS

You’ll need a css class selector for every character. Basically what we are doing is using the same background image for each letter. We’ll move the foreground text out of the way by giving it a large negative text-indent. Then for each span we set a different background-position so that only the portion of the image shows that corresponds with the letter of the span.

height: 25px;
line-height: 25px;

h1 span
background: url(char_trajan.gif) no-repeat left top;
display: block;
height: 25px;
float: left;
text-indent: -900px;

.letter_A { width: 16px;}

.letter_B { background-position: 0 -25px; width: 15px; }

.letter_C { background-position: 0 -50px; width: 17px; }

.letter_D { background-position: 0 -75px; width: 21px; }


As you see for every letter I not only shifted the background-position, but I also added a width. Since your cool font is probably not monospaced (where each character takes up the same width), we give each letter its own width. This will take some time. You have to first determine the width of every single letter of your image. In the print world, this is called adjusting the kerning.

What about special characters?

Since you can’t have special characters in CSS selectors (.letter_a is allowed but .letter_? is not allowed), then I gave the special characters special class names so they will keep feeling special. Isn’t that special?

In the PHP, I made a series of conditional IF, and ELSE IF statements to cover these special circumstances. Instead of using .letter_?, which isn’t allowed, I use .letter_quot. Now you can easily target that special character with CSS.

Text-wrapping and other limitations

Of course, with anything there are limitations.

  1. Wrapping text appropriately. Because every <span> tag is set to display:block and float:left, the word could easily wrap in the middle of the word. So long titles aren’t handled very well. I’m confident there’s a solution to this, but I’ll have to give it some more thought.
  2. You won’t find this in use on the headlines of my personal site because I’m using the built-in flexibility of Textpattern. TXP tags are great in how they allow you to easily insert common database data into your site, but it also prevents me from pulling my already-outputted dynamic text back into PHP for further formatting. If anyone knows a way around this, I’m all ears.

So that’s it. Any thoughts or questions?

See the Demo again

Discuss This Topic

  1. 1 Wulf

    One point to mention is that this technique doesn’t work (in its current form) if the user decides to resize the text of the page. Because the graphics are all specified in px in the CSS, the header will become progressively less dominant as the body font increases in size.

    Maybe you could specify all the CSS dimensions in ems or would that be to imprecise to allow a couple of steps of manual sizing up or down?

  2. 2 Tom

    Nice idea! But to be honest I still prefer sIFR. Wulf mentions the text sizing. I’d like to mention the loats of code you add to the HTML. Of course, this could be done by JavaScript.

  3. 3 Chris

    Hey Wulf, long time no speak! Resizing the dimensions using ems would work fine, but because the images themselves are fixed sizes that would just have the effect of making each letter have progressively more and more space around it as the user resizes the text up. You’d end up with V e r y S p a c i o u s H e a d i n g s :0)

    I agree with Tom, the whole HTML thing could be done by manipulating the DOM with Javascript. You culd then just pass in a list of heading levels (h1, h2 etc) that you want to be changed and some extra parameters and Javascript could do the lot for you.

    However I’m still convinced that the best way to do this is to create one image for the entire text and use an image replacement technique to display it instead of the HTML text. I did a quick solution in PHP using the GD library which you can see here (the demo is here).

    It allows you to use any TTF font on your system, at any size, any colour, with any background (transparently) and takes a load of parameters such as vertical spacing and alignment. It also checks to see if the image you are trying to create already exists, if it does it just reads the existing version. It’s not perfect, but it’s a pretty easy way to create fancy single-line text.

    There’s a lot more than one way to skin a cat :0)

  4. 4 bluesaze

    Looks like a good idea… I found SIFR to be a tad slow

  5. 5 Steve F


    This has been done before, look here:

  6. 6 Chris

    Steve – looks good, I wasn’t aware of that one.

  7. 7 Carl Camera

    Or, you could use Vine Type and it will do all of this for you—in any font—automatically—with text wrapping as well as PNG transparency so you can use it in front of patterned backgrounds (will serve up JPEG also) and it will even rotate the text for you. Oh, and it doesn’t require Flash and degrades well with images off. Okay, top that.

  8. 8 Chris

    Carl, that’s another one I wasn’t aware of. Couple of points knock it’s shine a bit: it’s not free ($20 for commercial use) and is written in .Net. Other than that, great!

    But you’ve set me a challenge for my AIRE function: rotate text, and multi-line input. I’ve also been meaning to make it OOP, so perhaps this is the right opportunity to do that. I wish I had more time to do it :0)

  9. 9 Nate Klaiber

    I am definitely with Chris on this one. I would much rather use GD and any typeface I needed and create the headers on the fly – versus manually building all letters and a long CSS file. Not only that, but its alot of extra markup to the HTML with all of the spans wrapping individual letters – especially if there are several headings on one page.

    I, personally, use PHP and GD to build headers. This allows for custom backgrounds if necessary, as well as custom fonts. Its one image that can be built and cached for easier retrieval. Using CSS I can do the image replacement for the headers (this is a topic for a whole other discussion…hehe).

    Anyway, I don’t think the idea is ‘original’ in its form – I have seen it done before. I just don’t like the overhead and bloat of it all. Extra HTML markup, extra CSS, and then splitting out each letter via preg_split and running it through a for loop to match the letters (I would bet that using GD to create the image would be much quicker as far as overhead – especially when used with a caching mechanism).

  10. 10 Natalie Jost

    I haven’t had the need for a fancy font on my site in a long time, but isn’t there a way to embed a font into the page so the CSS picks it up no matter what the browser/OS has installed? I’m surprised I haven’t heard people talking about this, but I could swear I read somewhere a couple of years ago that you could do that. I think it was just a matter of placing a TT font in a directory and linking to it in the header, kind of like a favicon. No?

  11. 11 Chris

    Natalie: there was a way to do it, but it’s long-since deprecated by now. Much the same as linking to external stylesheets you could link to an external font file – although I think it had to be .otf format – and then use that font throughout the page. Don’t quote me on that, though.

    The only site I ever saw this on was John Heron Project but despite a search in I can’t find a cached version to check the syntax. So, you get half-remembered information!

  12. 12 Kat French

    I’ve tried embedding fonts in the past without much luck. I’m not sure exactly what I was doing wrong, but I could never get it to work. I tried using EOT and all it did was slow down my page loads.

  13. 13 Tom

    Maybe Natalie means the font-face rule? AFAIK it’s no standard and Windows-only.

  14. 14 Andy Knight

    I appreciate all the comments. Even though I’d never seen a technique exactly like this, I never believed it was completely original or necessarily the best way to do image replacement. It’s just another way to do something that could be useful in certain situations. And if nothing else, maybe it gets you thinking and sparks your creativity to take it a step further and improve it. It’s good to learn from each other, right?

  15. 15 Chris

    Aha, this might be it: Looks pretty non-standard to me, though, because it says:

    “This method works in IE5 & IE6 but is not supported by Firefox/Opera.”

    Hmm, dubious.

  16. 16 Robert

    Nice Andy! I completely agree that even though it might not be appropriate for some circustance, it a leasts gets people thinking. Can’t please everyone though. ;)

  17. 17 Mike Montgomery

    Andy, great work.
    You’ve definitely highlighted the ongoing problem of fonts. How is it possible we haven’t solved this one yet?

    Admittedly, I don’t have any idea of what might be the difficulties, but font embedding or linking sounds wonderful.

    Perhaps the type foundries have objected to the “favicon” kind of font link. If so, they could look up from their current market size to the huge business of online music for inspiration.

  18. 18 Natalie Jost

    Chris, that is what I was thinking. It’s been so long though it makes sense it was an “ugly” non-standard solution. Would be so nice if there were a clean way to do that, though I imagine fonts being dependent on the operating system would make a browser’s direction irrelevant.

  19. 19 Morgan Stone

    To me one of the drawback of non-text titles is the inablity to be crawled by search engines.

  20. 20 Anthony "General Havok" John

    While I’d like to take the time to work out either a PHP or Flash option, here’s what I do in the meantime:

    {h1}{img /}H1 Text{/h1}

    .fly { position: absolute; left: -9999px; }

    In this way I can have a nice, fancy image AND make it spiderable as well. Admittedly, a solution that changes your text to images on the fly is MUCH cooler and less time-intensive, but until I have it worked out I’ll keep doing this. =)

  21. 21 Mike Montgomery

    Interesting post on web fonts availability at Clagnut: On fonts for the Web

  22. 22 Brennan

    Wrapping text appropriately. Because every tag is set to display:block and float:left, the word could easily wrap in the middle of the word. So long titles aren’t handled very well. I’m confident there’s a solution to this, but I’ll have to give it some more thought.

    I haven’t checked it with this, but white-space: nowrap; typically works pretty well for me.


Comments closed after 2 weeks.