Dynamic Text Replacement

Text styling is the dull headache of web design. There are only a handful of fonts that are universally available, and sophisticated graphical effects are next to impossible using only standard CSS and HTML. Sticking with the traditional typefaces is smart for body text, but when it comes to our headings — short, attention-grabbing blocks of text — it would be nice to have some choice in the matter. We’ve become accustomed to this problem and we cope with it either by making the most of the few fonts we have, or by entirely replacing our heading-text with images.

Article Continues Below

Most sites that replace text with images do so using hand-made images, which isn’t so terrible when there are a set number of headings, but it quickly becomes unmanageable on a site that is updated several times per day. However the replacement is performed, each image needs to be bound to the text it is replacing. That binding usually manifests itself as an <img> tag, an embedded style sheet, or a custom id attribute. And over time, through layout changes and redesigns, that binding needs to be managed by someone.

We can forget all that nonsense. No more <img> or <span> tags, no more id attributes or wasted time in Photoshop, and no more messy CSS hacks. Using JavaScript and PHP, we can generate accessible image-headings using any font we like. And we don’t have to change the structure of our HTML or CSS at all.

View the demo to see Dynamic Text Replacement in action. Then read on to find out how you can add the same functionality to your site.

PHP#section2

This small PHP script (available here) will deliver a dynamic PNG image to our browser whenever it’s asked to. Before we set it to work, though, it needs to be customized for your specific purpose. The first seven lines of code in the script serve this purpose:

  $font_file = 'font.ttf' ;
  $font_size = 56 ; 
  $text_color = '#ffffff' ;
  $background_color = '#000000' ;
  $transparent = true ;
  $cache_images = true ;
  $cache_folder = 'cache' ;
  • The $font_file variable must be set to the local path (not the URL) of a True Type (TTF) or Open Type (OTF) font on your web server. This is the font that your images will be created with; you’ll need to upload it to the web server from your own computer.
  • $font_size, unsurprisingly, refers to the size of the font in points.
  • $text_color and $background_color are hexadecimal color codes that indicate the color of the text, and color of the image’s background, respectively.
  • When $transparent is set to true, the edges of the image’s text will be blended with the $background_color to prevent anti-aliasing, and the actual background color will be entirely invisible.
  • By setting $cache_images to true, and $cache_folder to the local path of a writable directory on your web server, this script will save each image that it creates, caching them for later use. This can significantly speed up delivery of images to your visitors, and is particularly important on shared, or high-traffic servers.

To install this script, upload it to a web server that is configured with PHP support. Specifically, you will need PHP version 4.3 or higher, compiled with support for the GD graphics library, 1.6 or higher. If none of that means anything to you, email those requirements to your web host and they’ll tell you if your server is compatible.

Although we used PHP to construct the images in this implementation, your website does not need to be actively using PHP to take advantage of this technique. Regardless of how you generate your HTML pages, whether they’re edited by hand or through a CMS, you can use this technique as long as you can insert a <script> tag into the <head> of your documents. I’ll explain that detail further, below.

Please note that what can be done with PHP can often be done with other tools as well. Perl, ASP, Java servlets, and other server-side programming languages would also be good candidates for generating custom images. PHP is an excellent choice because of its wide availability, platform independence, and easy learning curve. Consider the alternatives if you require something that PHP doesn’t provide or if you choose to create your own image-generation code from scratch. It might be simpler, however, to just adapt the PHP code presented here.

One thing that our customization of the script did not include was the text that it should use to generate our custom images. That’s because the text that we’re using to produce these images will be passed to the script via its URL. For example, loading the URL heading.php?text=URLs Are Fun will produce a graphic that reads “URLs Are Fun.” And they are. But we’ll never need to write them ourselves, because JavaScript will do it for us.

JavaScript#section3

Download the JavaScript source file here.

This technique borrows heavily from Peter-Paul Koch’s JavaScript Image Replacement (JIR) method. The premise of JIR is very simple: Many CSS coders exploit browser bugs to hide CSS styles from those browsers. These hacks are akin to limited conditional statements in their code, turning CSS into a crude programming language. Rather than using this language-of-bugs to compensate for browser differences, Koch and others have put forth the idea that JavaScript — an actual scripting language — could more intelligently and accessibly perform the same task. This is wonderful for our purposes because JavaScript also gives us more flexibility. Specifically, we’ll be using it to replace text with images that don’t even exist yet.

When the page first loads, the script will attempt to load a small (1×1 pixel) test image. If this test is successful, we can conclude that the visitor’s browser supports the display of images, otherwise it would not have wasted bandwidth downloading it. This is the crux of JIR: By testing for image support, we can immediately determine whether or not our visitors have any use for stylized headings. If they do not, the script will stop right there.

Assuming the visitor’s browser supports images, the script then waits until the page is entirely finished loading, because it can’t replace text that hasn’t been downloaded yet. Once the HTML is finished loading, our script will search it for specified elements (<h2>, <span>, etc.) and replace the text inside of them with an <img> tag. This dynamic <img> tag has its alt attribute set to the original text, and its src attribute set to the URL of the PHP script that we just installed. The PHP script then sends back a custom PNG image, and voila: custom headings.

Weighing in at a hefty eight kilobytes, there’s a lot of stuff going on in this corner of the ring, but there are only two lines that need to be customized before the script will work.

  replaceSelector("h2","heading.php",true);
  var testURL = "test.png";

The replaceSelector function accepts three parameters: The first is the CSS-style selector that indicates which elements should be replaced. This selector may be almost any valid CSS selector, including id, class, element and attribute selectors.

The second parameter is the URL of our custom PHP script.

The third parameter is a true/false value that indicates whether word-wrap should be turned on for this replacement. When this flag is set to true, headings are broken into multiple images, one for each word. When it is false, only a single, non-breaking image is generated for each heading.

replaceSelector should be called once for each group of elements you want replaced by a custom image. The URLs in these lines can be absolute (http://…) or relative to our HTML file (path/filename).

The testURL variable needs to be set to the URL of a small (1×1 pixel) test image.

Once these lines are set correctly, you can upload the JavaScript file to your web server, and apply it to your web pages by adding the following line to their <head> tags.

  <script
    type="text/JavaScript"
    src="replacement.js">
  </script>

Make sure the src attribute in that line points to the location that you uploaded the JavaScript file to.

That’s all that’s required to get dynamic text replacement working; we can stop right there if we want to. But there are a few optional improvements we may want to make before calling it quits.

Print Versions#section4

As previously seen here in ALA, many sites are now employing specialized printer style sheets to give their visitors better hard copies of their content. In many cases this involves reversing the process of image replacement so that the printed copy of a page uses actual fonts rather than graphics, which often look poor on high-resolution printers. Unfortunately, JavaScript falls short of solving this problem. Once we’ve replaced our text with an image, it’s impossible to reverse that process specifically for printing purposes, so we need to find another solution.

Instead of trying to reverse our replacement process, we can do a little planning ahead. Along with inserting an <img> tag into our headings, we can also insert a <span> tag that contains the original heading text. And we can set that span’s display property to none, so that it doesn’t show up onscreen. Now we have two copies of our original text: One in a visible image, and one in an un-displayed span. By giving each of these elements identifiable class attributes (“replacement”, and “print-text,” respectively), and by adding in a print-specific style sheet, we can swap their display properties when they’re printed.

The following style sheet (download a sample CSS file here) could be used to generate an appropriate print version of your page:

  span.print-text {
    display: inline !important;
  }
  img.replacement {
    display: none;
  }

Once we’ve uploaded this style sheet -to our web server, we only need to change two lines in our JavaScript to make it work:

  var doNotPrintImages = false;
  var printerCSS = "replacement-print.css";

By setting doNotPrintImages to true, and printerCSS to the URL of the print style sheet we just created, the script will automatically insert the appropriate CSS <link> into our document’s <head> tag.

Flicker Free#section5

Because our script can’t begin replacing elements until after the entire document has loaded, there will often be a quick flash of unstyled content as the browser waits for the replacement process to begin. This is less of a problem than it is a minor annoyance, but since it’s avoidable we might as well fix it. With the help of another small style sheet, we can do just that.

Before the document’s body begins loading we can dynamically insert a style sheet that will hide these elements entirely. Since linked CSS files are applied even as the document is rendering, no content will be visible during this period. Once our replacement technique is finished executing we can disable this style sheet and our newly stylized headings will be visible once more.

For example, if your page was set up to replace <h2> tags, the following style sheet (available here) would hide them until our replacement technique was finished:

  h2 {
    visibility: hidden;
  }

There is a slight problem with this approach, however. Our entire technique depends on the loading of a test picture to indicate whether the browser supports images. If the image never loads, our technique will never activate. And if our technique never activates, the style sheet that hides our unstyled headings will never be deactivated. Because of this, visitors who have disabled image support in their browsers, but who are still capable of using JavaScript and CSS, will see nothing but empty space where our headings should have been.

We’ll do our part to improve this poor minority’s already-difficult browsing experience by adding a short timeout value to the script. If the test image hasn’t been successfully loaded after one or two seconds (or however long you see fit), the script will automatically disable this style sheet, and the headings will reappear. Those one or two seconds are a slight inconvenience for this exceptionally rare person, but it solves the flicker problem for the other 99.99% of our visitors. What’s important is that we maintain accessibility for everyone.

To enable this optional customization, and to remove the brief flash of unstyled content, you must edit three lines in the JavaScript source:

  var hideFlicker = false;
  var hideFlickerCSS = "replacement-screen.css";
  var hideFlickerTimeout = 1000;

Set hideFlicker = true, and hideFlickerCSS to the URL of the CSS file that you just created to hide your headers.

hideFlickerTimeout should be set to the maximum number of milliseconds (i.e. 1/1000 seconds) that the script will let pass before disabling that style sheet.

Notes and Suggestions#section6

Older versions of Mozilla, including Netscape 6.2, contained a bug where the browser would download images even if the user had instructed it not to display them. This obviously made no sense, and has been fixed since version 1.4. Although this technique will normally work without any problems in these browsers, it will incorrectly diagnose image support and fail when visitors using these browsers have images disabled. I don’t consider this overwhelmingly rare occurrence to be a serious drawback, but it’s worth noting for completeness. There is currently no workaround for this problem.

Use this technique with a translator service, like Google or Altavista’s Babelfish. As long as your font supports the foreign character set, the dynamic images will be translated as well.

The text that you replace does not have to be inside of a heading tag (<h1>, <h2>, etc.); it can be any element on the page. With some fairly simple adjustments, and some manipulation of float values, this technique could produce dynamic drop-caps for any paragraph you apply it to.

You can also replace <a> tags, giving your page stylized hyperlinks, although getting rollovers to work would require more customization.

Instead of replacing content with dynamically generated <img> tags, this technique could avoid using PHP altogether and instead insert dynamic Flash animations.

Acknowledgements#section7

Peter-Paul Koch, for his JavaScript Image Replacement technique.

Simon Willison, for this getElementsBySelector function.

Stuart Langridge, for unobtrusive JavaScript techniques.

About the Author

Stewart Rosenberger

Stewart isn’t going to use this space to plug a website you’ll never visit. He’s a computer technician at the University of Massachusetts. If you say “please,” he’ll probably hold your place in line or feed your pet rock while you’re on vacation. He’s a really nice guy and he likes animals; he doesn’t think you should eat them anymore.

280 Reader Comments

  1. Is it not an Accessibility requirement that you must be able to resize text? with this method I don’t see the possiblity of increasing the size of the dynamic images?

    Other than that minor flaw, the method is excellent!

  2. Good question, however, if we look at accessibility in a logical way, it does not make sense to only zoom the text anyway. Screen magnifying software (every OS these days has inbuilt ones) magnify the whole screen. So does Opera, btw. It would be interesting to see how much more users use these tools rather than the hard to find (at least in IE) browser zooms.

  3. One method to solve the accessibility method is to add a JavaScript script which doesn’t just increase the font size, but also loads new images.

  4. Interesting idea. Personally I find it a bit heavy and limited, as you can’t kern or otherwise manipulate the headline image dynamically. This could lead to fitting problems.

    The other flaw is that this doesn’t work for screen readers. Most modern screen readers use IE as the rendering engine, and merely speak everything that it sees. If the javascript replaces the headlines with images, they will no longer be read.

    This however is untrue in regard to text-only browsers. Obviously they will work “properly”, as the text will not be replaced.

  5. Does this method allow for different coloured matts? or are the images using an alpha channel? Also is it possible to set the images to render with only one picture as the volume of connections this would create could affect busy sites. Im certainly not criticising this. I think its a wonderful idea, just some thought for version 2 🙂

  6. Anyone care to make an asp.net version of this? Microsoft uses dynamically generated in a lot of places now: see the gray banner “Microsoft Windows Small Business Server 2003” at http://www.microsoft.com/windowsserver2003/sbs/howtobuy/default.mspx
    They use an asp.net script with the text to display encrypted as parameter to generate these headers: http://www.microsoft.com/library/toolbar/3.0/subbanner.aspx?t=TWljcm9zb2Z0IFdpbmRvd3MgU21hbGwgQnVzaW5lc3MgU2VydmVyIDIwMDM%3d&f=FFFFFF&b=757575&s=A7A7A7&r=False&font=Segoe%2c+13pt&v=0&c=HgjbLWiigY01WAeFBYwa4dzXjGY%3d

  7. To answer some questions posted here:

    1) Yes, this method allows for different matte colors. The matte color (if transparency is chosen) will be the $background_color variable. No alpha channels are being used (because of IE’s lack of support), but this script could be altered to do so, if you were inclined.

    2) As mentioned above, screen readers should all read this text correctly, because the ALT tag is maintained throughout this process. To my knowledge, no screen reader will ignore an ALT tag, if it is present.

  8. Safari (v1.2.2) doesn’t store the replaced images in cache, so each time you reload the page you have to wait for the images to load. This doesn’t occur in Moz (and I haven’t tried yet in other browsers).

    The HTTP headers sent by the PHP script are :
    Date: Tue, 15 Jun 2004 14:17:51 GMT
    Server: Apache
    X-Powered-By: PHP/4.3.7
    Keep-Alive: timeout=15, max=99
    Connection: Keep-Alive
    Transfer-Encoding: chunked
    Content-Type: image/png

    Maybe adding headers like “Expires”, “Cache-Control” and “Pragma” will force Safari to store them ?

    Cheers.

  9. Very interesting solution. However, if I understand things right you have to edit a php file to change the color and a js file to change the font (or is it the php file for both?). Not exactley convienient. What happens when you want an alternate stylesheet with different colors and/or fonts? While this method may work great for some, I just don’t see it working for everyone. Now, if there was a way to define the color, font, textsize, etc in the css and use that data to create the images I could see this as a more usefull solution.

  10. Replacing text with a link in it seems to lose the link… any workaround?

    link

    becomes a nonclickable heading…

  11. Chris: it is true that modern browsers like Opera allow you to scale everything on a webpage, including the images. Hoewever, if you’re visually impaired (like me), it’s not nice to read titles that look like ugly pixelated bitmaps when they’re enlarged.

    If you would use vector titles (Flash or SVG), then the enlarged titles would still look crisp and be a lot easier on the eyes. Opera does a very good job on enlarging pages that consists of plain HTM text and Flash applets (don’t know about SVG), but bitmaps will be bitmaps…

    btw: enlarging an image is also possible in Firefox. The Mouse Gestures extension has a very intuitive and elegant way tot do that and I use it a lot when I need to read small bitmap print on webpages. To read the small vector fonts in Flash applets, I usually just use the ‘Zoom in’ function on the context menu of a Flash movie.

  12. waylman: Both the font and the colors are stored in the PHP file, which generates the images. Although it would be nice to store this image in a CSS file, and dynamically apply it, it would require a lot more Javascript to do so, and the JS file here is already 8k in size. Either way, it’s still better than specifying your font/colors in Photoshop.

    ceejayoz: You can make linked-headings work by replacing the link tag, not the heading. If you replace the heading, the link will be wiped out.

  13. Haven’t tested it yet, but this is how I would go about doing it:

    Modify the image generating script to take its parameters from the $_GET array. In the php script specify some defaults, and update the appropriate properties supplied to the script.

    In javascript create an additional function (get_font_style(selector)), which would determine the style information for the text which is to be replaced.

    Then just sit back, and call
    replaceSelector(selector,get_font_style(selector),true);

  14. correctly spelled is: Peter Zsoldos. I think I just my rights to make fun out of all my non-HUngarian friends who can’t spell it. ouch.

  15. This article is very impressive. Font restriction is quite a frustration when you move from DTP to web design. This solution is just great, thanks a lot.

  16. This is definitely a neat technique, but it seems a bit processor and bandwidth intensive, especially for a large, content managed site (which seems to be where it’s targeted). Why not generate the images when the content is added? While it would require modifying the CMS slightly, it might be a better overall solution.

  17. I used a strikingly similar method for a while(pure php, no javascript), but eventually realized straight up text was ok for me. 🙂 I used http://mmcc.cx/php_imlib/ which has some interesting text manipulation routines text direction, bluring, layering etc. At the time(a year or so ago) I hadn’t yet embraced pure xhtml/css so I simply had a php function any of my pages could call. get_path_for_text($str) It returned the img block with appropriate alt tags etc filled in.

    If you wanted something hackish but controlable via your css sheet you could take on a method like the following. Setup a generic class that isn’t being used elsewhere in your xhtml, and have your text generation script parse the color,size,font,etc from your css(using php of course) This would still work with the caching mechanism, but you’d have to check to make sure your css file was older than your cached image, you can do this with stat(a php builtin function). If your image was older than your css, you treat it as non-existent and generate(overwrite) a new one. This wouldn’t be hard functionality to add to the script posted with this article.

  18. I was wondering if dynamically creating images in this fashion will take up extra bandwidth or server resources. On a large site it would seem that a technique like this could cause extra work for the server and possibly slow down your page.

  19. Yeah, images are gonna be larger than simply transmitting the text. They’re not gonna be huge though, and that’s a trade off for getting a slightly more artistic presentation. Note that they’re not regenerated every time the page is loaded, when it generates the images the first time it keeps them on disk. So the next time it realizes “Hey ! I’ve got one of those right here, no need to bother creating it.” It allows you to not have to go into photoshop/the gimp everytime you need a new image for your templatized text.

  20. I think this technique is superb. The main problem I have with any text-replacement method is the fact that there is no line-wrap. I’ve come very close to getting the Flash Image Replacement to successfully wrap, but haven’t quite got that to work. This looks like a great solution to some of the more difficult gif-based dynamic text solutions I have seen. I appreciate the PHP, but is there anyone out there skilled enough to make this work in ColdFusion?

    Thanks for a great article.

  21. First of all, it is an alt ATTRIBUTE, please stop using the term alt TAG. Secondly, all windows based screen readers do use the IE engine, but read out the content on the screen, not generated content via DOM. It is easy to claim a lot about things not being accessible, another to simply check it in the real environment.

  22. As others have pointed out, my code only generates each image once, and then stores it. Sending the image again has negligible overhead.

    I wouldn’t recommend DTR for a site that needed to replace more than a handful of headings per page. But on a page with even half a dozen headings, this method saves a lot of effort, and doesn’t significantly add to page load time.

    Ryan: Line wrapping is, in fact, supported by this technique. By setting a simple flag in the Javascript, you can have it generate a separate image for each word. As long as this images have the same baseline (which this PHP script ensures), the words will line up and wrap correctly.

  23. If I turn line-wrapping on in the JS file, I get a bunch word-images butting right up against each other. Is anybody else having this problem? It’s happened with two completely unrelated(different foundry and designer) fonts so far.

  24. I’ve been thinking about this very idea for quite some time now, in ASP.NET of course. I’ve written several handy image manipulation/generation objects for my own personal use (auto thumbnail creation, importing images from my digital camera) and have had some ASP.NET code that was fairly well suited for this purpose sitting around, just begging me to apply it to this very subject.

    As ALA always does, the fire under my butt has been lit and I’ve got a nice working script available:

    http://software.enjoybeing.net/dev/gen_heading/generator.aspx?h_text=Look+At+This+Auto+Generated+Text!

    The thing I am now struggling with is retrofitting the JS code from the article to work with my .NET page.

    Something I don’t understand is the usage of the testURL and test image. The JS seems to initially request a PNG image and appends a querystring value to it… this seems quite odd because what is an image going to do with a query string value?

    I think the idea of generating header text OTF (on-the-fly) is the way to go, makes other image replacement techniques look stone-age.

    As not to fill up this discussion with technical talk about ASP.NET solutions to this idea, feel free to drop me a line via:
    http://software.enjoybeing.net/contact/

    Great article!

  25. Justin: The testUrl.src has a query string appended to it as a precautionary measure. We append the current time (in milliseconds) to the URL string so that it never requests the same URL twice. This should prevent browsers from caching the test image.

    Although caching the test image might sound like a good thing, this idea was put forth by Peter-Paul Koch to prevent browsers that cache the image from not firing the Image.onload function (since the image is already loaded). If the testImage.onload function does not fire, we can’t be sure that the browser supports images at all, which is a key factor in this technique.

  26. Is there any way to apply this only to tags with a specific class like {h2 class=”font”} ?

    I would like to be able to use this to generate just one letter in a heading like {h2}{span class=”letter”}H{/span}ello{/h2}, but it seems I can’t do it without eating up the whole span tag.

    Any ideas?

  27. Can this technique be done straight up without converting to images?

    As in can you load a font onto your server, and then have the font appear on your site, without it being converted to an image – and the other person still being able to see that font?

    (I’m going to guess no, but if it’s a possibility I’ll be more than happy to hear that solution.)

  28. As long as you’re not using alpha transparencies, Internet Explorer (and every other modern browser) should support PNG just fine.

    PNGs are preferable to GIFs in most cases; they allow a wider range of colours and compress better.

  29. Got that ASP.NET version completed, changed the image type to GIF and had to make the test image (test.gif). I just changed the URL’s for the h1 and h2, changed the test image to a GIF, that’s it.

    I also had to modify my .NET code a little bit, changed the querystring parameter name. Therefore my previous example I posted no longer works. This is because I originally used “h_text” for the querystring key, now it uses the same key as the PHP equivilent, which is just “text”.

    Here’s the final product:
    http://software.enjoybeing.net/dev/gen_heading/

    Since I apply an underline to the image text, it is obvious that the JS code sends a request for each individual word rather than the entire string of text enclosed in the H2 tag… isn’t this a waste of resources (not to mention the underline effect is lost). Also, it would be problematic if the dynamic image performed more advanced techniques, such as gradients or predefined images before/after the string of text.

    Let me know how it works, again, feedback here:
    http://software.enjoybeing.net/contact/

  30. Javan: By customizing the javascript code, you can change which selector is used to find replaceable images. So instead of writing “h2”, you could tell it to replace “h2 span” which — like the equivalent CSS selector — would only target tags that are inside

    tags.

    marty: unfortunately, it’s not possible to do this without images. Font embedding is supported by IE/Win, but it’s not standards-compliant. Until a better solution is supported by different browsers, we’re stuck with either images or Flash.

  31. For the prompt reply.

    I figured as much. Cool article, and we will attempt to use this technique in the near future.

    M.

  32. Just in case anyone is trying to do this, there is a quick and easy way to turn of antialiasing of fonts, which is pretty much nessecary for bitmap fonts and obtaining the “pixely” effect. Just go to line 94 of the PHP script and insert a – (negative/minus sign) before $font_color. (For the people who aren’t fluent in basic programming, that just negates the number, or the color index in this case.) For some reason, that’s the only way to disable anti-aliasing when using the imagettftext() funtion.

  33. If you want to resize the font you can simply send that as another parameter in the image tag. So
    heading.php?text=URLs%20Are%20Fun
    becomes
    heading.php?text=URLs%20Are%20Fun&font_size=72

    then some minor edits in the PHP file and you can dynamically resize, re-colour, and re-font, all your headline images at once!

  34. The downside of »display:none« for the print text in a browser that doesn’t load images *and* stylesheets: Doubled text.

  35. The only browsers that support images and javascript but not CSS are older browsers, and this script uses object-detection to ignore them. So Navigator 4.0, for example, will not apply this technique.

    It’s conceivable that someone could manually disable CSS in a modern browser, but why would anyone do that? And if they did, why would they leave regular images enabled?

    I don’t believe this is a serious concern.

  36. i am not a javascript guru, etc., but here is an idea:

    extend the php/GD/etc. script to create multiple images with different appearances, give them names that can be referenced within javascripts or css code that perform rollover and style-switching in the manner described in several other ALA articles??

    i imagine this would require standardizing the image filenames created by the php/GD/etc. script so the javascript knows what to do…

    seems also possible that the php code could also dynamically create the actual javascript code or know which javascript filename to write into the code…

    this would make a good part 2 / part 3 follow-up to this excellent article.

    thank you for reading this…

    🙂 tom

  37. Wow! This quite the trick.

    Im excited (mabet a little to excited!) by how much impact this will add to my sites using content management systems and how easily it will be to plug-in.

  38. I was not aware when I wrote this article, but Shaun Inman (http://www.shauninman.com) developed an similar technique in April of this year. His technique uses Flash exclusively, rather than PHP images, but the principle is virtually identical.

    While I believe that both of our methods have benefits over one another, Shaun very clearly came up with this idea first. Had I done better research beforehand, I would have either credited Shaun with the development or decided against writing the article entirely.

    Anyone who’s interested should check out Shaun’s fantastic replacement technique at http://www.shauninman.com/mentary/past/ifr_revisited_and_revised.php

  39. I just wanted to add my $0.02 about accessibility issues with this technique.
    1. “if images are requested then the user can use them”. This is false. Most people with visual impairments or blindness surf with IE win and images on. You can’t tell whether the user will be able to see the images in any way from the server end. Very few special needs users use text-only browsers.
    2. Images cannot be recoloured on the fly or resized unless the user has special software such as the screen magnifier SuperNova and knows how to use it. There are many serious accessibility issues caused by these limitations. These issues can be minimised by ensuring that there is high contrast between the foreground and background colours, that a sans-serif font is used, that the text size used is large enough to compare with IE’s large setting for body copy, that the design does not use commonly confusable colours such as red on black, red on brown etc etc, that the images are not placed over a background image.
    3. The bottom line is that yes, you are compromising accessibility using any of the image replacement techniques; In real world web design we need techniques like these, but the question is whether you apply some common sense to minimise the additional problems you are causing.

  40. No-one has yet pointed out the issue of copyright. I assume it would be illegal to upload your favourite fonts to the server. Can freeware fonts be copied in this way? Or does it not matter since the fonts are turned into images? (I can see the law defining uploading the font as “copying” it, and even distributing it as the server contents are mirrored, that’s all.)

  41. I have been playing around with this script (i.e. these scripts) for a while. Great idea. And some great hints in this discussion either. However, I was wondering about special characters that you might need in foreign languages.

    Is there any way to have a ö character? It is said that this should cause no trouble to the script, but in fact it does not work.

    Any ideas?
    Ansgar

  42. Shaun shared his IFR technique with us as a potential ALA article before publishing it on his site after we decided to pass on it.

    We thought Shaun’s technique was marvelous and innovative, but we had some problems with it, and declined it.

    With the present article, no such problems presented themselves, so we approved and published Dynamic Text Replacement.

    The two techniques are different and were evolved independently. Both have their strong pluses. For us, the accessibility benefits of DTR made this article an easy buy.

  43. >>No-one has yet pointed out the issue of copyright. I assume it would be illegal to upload your favourite fonts to the server.

    I’m no expert on intellectual copyright law, but I don’t see why you make that assumption.

    This method does not embed copyrighted fonts on the page. This method simply creates GIF images of text. It’s no different than opening Photoshop and manually creating type GIF images, except that the process is automated.

    Is your concern that someone might hack their way into the system and download the font without paying for it? If that is your concern, I must say it seems unlikely to me that a dedicated hacker would expend energy trying to steal a font from myclient.com. For one thing, said hacker would have to KNOW that the type GIFs on the page are being dynamically generated via a font stored on the server. And how would he or she know that?

    Besides, why rob a lemonade stand when you can rob a bank? It seems to me that any dedicated hacker determined to download fonts without paying for them would spend his or her time trying to attack Adobe.com or Veer.com — not my clients’ sites.

  44. You normally pay for the use of a typeface on a X x CPU licence basis.

    In effect you pay to use on an agreed number of computers (normally 1x, unless its a bulk licenses) – uploading it to a server (as you need to do in this example) is an additional CPU.

  45. WOW. Using PHP to dynamically create an image (or 3-4 or however many) on every page hit CERTAINLY won’t be a resource drain on a server… right? Doh! Even with image caching this still seems unreasonably wasteful.

    Shouldn’t we be designing in a more typeface independent manner in the first place?

  46. Sending cached images to a browser incurs almost no overhead. The processor requirements for loading a PHP file and checking whether the file exists is virtually nothing. Compared to something like database access, sending a static file is practically a day off for the server.

    There is something to be said for designing in a “typeface independent” manner. Let’s be pragmatic, though: current web design only provides maybe seven universally accessible fonts to choose from: That’s not a lot of choice, and this method is simply another option for designers who have tighter requirements.

    Having just visited your website, I can see that you’re not in total disagreement: Well over half of the words on your home page are represented as images.

  47. This is a really great article, and something that I’ll find very helpful on my next project.

    I also had trouble with no spaces appearing between the words. I added this line to function javascript_to_html($text)

    $text = $text.’ ‘;

    which seemed to do the trick… although I’m guessing there’s probably an easier / cleaner way to fix the problem.

  48. Cool article, but…

    Ever since I viewed the demo, my fonts have been screwed up. If I view some emails in Outlook or view some websites, the font that was used will show up. It’s quite annoying.

  49. This is a great example of a technique, which is a plus for sales, for getting bigger profit from your CMS. This technique will please customers. It will generate more cash.

    I love it 🙂

  50. >You normally pay for the use of a typeface on a X x CPU licence basis. In effect you pay to use on an agreed number of computers (normally 1x, unless its a bulk licenses) – uploading it to a server (as you need to do in this example) is an additional CPU.

    Aha. Now I’m with you. Yup, you might have to pay a licensing fee for storing an additional copy of a font on a server, depending on the font house and its licensing fee structures.

  51. Another legal issue I’d be concerned with is people downloading the font — either someone with FTP access or someone who just figured out the URL. I’m probably just being paranoid, but I can see it happening.

  52. If you were concerned about someone downloading the font by figuring out the URL, couldn’t you just rename the font file X3CR3L.TFF or something similar?

  53. Some sanity checking should probably be added to limit the total number of cached images as this could be used as a DoS on the servers’ available disk space.

    Otherwise, someone could just run through the dictionary and start creating boatloads of images of worss.

    Just a thought.

  54. >Shouldn’t we be designing in a more typeface independent manner in the first place?

    If by “designing” you imply “communicating in a visual medium”, I’d have to say no. Designing without typography is akin to writing without verbs. You may get understood, but it’s crude, as is the typographically poor web of today. Good typography is the result a few thousand years of development; it should not be dismissed because current technology isn’t (yet) able to fully exploit it.

  55. Does this system re-renerate the images every time the page is loaded, or once a session, or are the images saved to a temp dir or to the websites webspace.

    The reason I ask is because image generation can be a pretty taxing thing for an application server, particularly for highly traffiked websites.

    Any thoughts?

  56. OK, I do everything with standards now, but I am coding a freelance 300page website that needs to work all the way back to the dreaded Netscape 4.77 and IE 5.0, for education. We figure for an education site, schools could very well be using old browsers + computers.

    So my question, does this PHP script work with legacy browsers like N4.77? if it does, awesome! I really don’t want to wind up producing hundreds of image headers

  57. Great article, just one question though, when comparing the dynamic headings with those I created in Photoshop, the dynamic ones are far inferior in quality – to the extent I couldn’t bring myself to switch over.

    I’m using the same font size, background & foreground colour, etc, and have played around with the settings in the scripts but to no avail. As an example, here’s one of my PS headers – http://pacepro.cameronyule.com/images/welcome.gif and here’s a dynamic one http://pacepro.cameronyule.com/heading.php?text=Welcome%20to%20Pace

    Any ideas? Or is it back to manual graphics for me >:(

  58. Pardon me but I’m not much of a PHP coder. I’ve been trying to implement dynamic text replacement but somehow the text graphics are not showing up on my page.

    I know my webserver has PHP version 4.3.5 with gd enabled. I have my font and files in the right places. The php code is being executed without any error messages but no images appear, I get the icon for broken image links instead. What am I doing wrong, or are there server-side issues I have to troubleshoot first? Thanks.

  59. Has anyone had problems with IE caching images sizes with this technique?

    When I change fonts or sizes, IE still uses the image sizes of previous fonts, so the text look really ugly.

    Mozilla and Opera (obviously) don’t have this problem.

  60. by adding a boolean called clearcache in de javascript file, and by adding this to line 90 of that file:

    [code]if(clearcache) url += “?date=” + (new Date()).getTime();[/code]

    you force IE to clear its image size cache.

  61. I noticed that IE bug as well. Your fix works, but by addding a unique string to the end of the image’s URL, you’re preventing *any* caching, which may not be ideal.

    I’ve found it better to slightly change the URL of my PHP file whenever I alter the font-settings. That way, my visitors can cache the images without worrying about this stupid IE bug making the headings pixilated.

  62. The php itself could cache the images so that they are only generated once per heading change, otherwise the php redirects to the cached image saving server load of GDI. Not a huge deal on low traffic websites but every processor cycle helps on larger ones.

  63. if you have a CRLF and/or TAB after the opening tag, but before the characters, Mozilla will pass PHP the escaped CRLF and TAB characters to render in the images.

  64. I’m having a problem with one TT font file in particular. I have no problems with any other font that I try. For this problem font, the image shows up as a series of “boxes” instead of the text. The font looks fine in any other vehicle that I use to view it.

    Of course, this problem font is the font that I really want to use 🙂

    Anybody have any ideas?

  65. A very very good point! On a static site you could get around this by generating (by whatever method) a list of all the words in the headings on the site whenever a new revision is uploaded and only letting the php script return those, but on a dynamic site you may find that your headings are dynamic (is the case for me) so that’s not a viable option…

  66. PHP is a server-side language, that means it’s operation is completely unaffected by the browsing medium. This is as opposed to Javascript which is a client=side language.

    With Netscape 4.7 you may have troubles running the JS file, though I’m sure someone here could make it work – but that person isn’t me, I shamelessly turn a blind eye to anything prior to Netscape 7 😉

  67. As mentioned in the article, it is possible to use this technique to replace tags with dynamic Flash movie.

    A simple test page exists with downlaods available for additional/altered files at http://www.famfamfam.com/flash/dtr

    These do not have the overhead of running PHP scripts to create image content, although they do have problems as you can most likely see; Flashes of unstyled/unsized content, and differing appearance on various browsers are among the current bugs. Most, if not all of the bugs with this are fixable for anyone who has the time. I hope someone is interested enough to finish off this alternative method for a great technique.

  68. Isn’t there any possibility to use this script in a server that has only php 4.1?
    I asked the admin, and he said he can’t upgrade php. I could change the server, but this is from a friend and is free to me.
    Is there any modification i can do to make this technique works in php4.1?
    the gd is installed in the server.
    The technique is great, i’d like to use it.
    Thanks.

  69. In IE for Windows, if you go to Internet Options -> Security -> Internet and set it to High, then this does not get run at all. If it’s set to Medium it runs, but not on High.

  70. Bruno: PHP 4.1 did not come with the GD library support by default, but if it is installed on the server, and the module is included in PHP, then this technique will work fine.

    Brian: IE with “high security” disables all ActiveScripting support, which includes Javascript. So, naturally, that would disable this technique entirely. However, if the Javascript does not execute, the standard headers will still remain, and they can still be styled using standard CSS techniques as a fallback.

  71. I’ve implemented a similar technique on a new site, but the prospect of a little unobtrusive automation intrigued me. The problem is that I have several headings that need replacement, all with different styles and colors. My solution moves most of the configuration into the page calling the scripts.

    The javascript in the main document is like this:
    <script type=”text/javascript”>
    function imageHeader(selector,phpfile,wordwrap){
    this.selector = selector;
    this.phpfile = phpfile;
    this.wordwrap = wordwrap;

    }
    var imageHeaders = [
    new imageHeader(“h5″,”heading.php?font_size=14&font_color=00ABE4&background_color=FFFFFF”,true),
    new imageHeader(“h2″,”heading.php?font_size=22&font_color=FFFFFF&background_color=CCC592”,true)
    ]
    </script>

    In replacement.js , I’ve replaced this code
    replaceSelector(“h2″,”heading.php”,true);

    with this code

    for (var i = 0; i < imageHeaders.length; i++) {
    replaceSelector(imageHeaders[i].selector,imageHeaders[i].phpfile,imageHeaders[i].wordwrap);
    }

    Also in replacement.js , replace this code:
    var url = items[i].url + “?text=”+escape(tokens[k]+’ ‘)+”&selector=”+escape(items[i].selector);

    with this code:
    var url = items[i].url + “&text=”+escape(tokens[k]+’ ‘)+”&selector=”+escape(items[i].selector);

    Finally, in heading.php , set up the PHP script to accept those variables from the query string

    if($_GET[’font_size’]){ $font_size = $_GET[’font_size’]; }
    if($_GET[’font_size’]){ $background_color = $_GET[’background_color’]; }
    if($_GET[’font_size’]){ $font_color = $_GET[’font_color’]; }

    It would be so nice if the javascript could parse the CSS color: , background-color:, white-space: and font-size: properties to populate that query string for the PHP script. This way, we’d only have to include the javascript in the head and ALL the styles would remain in the stylesheet where they belong.

  72. Ok, but the server where i host my site has PHP 4.1 with GD support and it doesn’t work there. I get lots of “The server could not create this heading image” errors.
    Is there anything i can do to solve this?
    Besides having GD support, my php must have any other functionality? May it be necessary any modification in the script?
    I hope so…
    Thank you..

  73. Likewise, in heading.php you could add this at line 25, just below $cache_folder…

    $selector = $_GET[‘selector’] ;

    if($selector == “h2”) {
    $font_file = ‘supercoolfont.ttf’ ;
    $font_size = 12 ;
    $font_color = ‘#ff6600’ ;
    $background_color = ‘#ffffff’ ;
    $transparent_background = true ;
    $cache_images = false ;
    $cache_folder = ‘/whatever’ ;
    }

    I’m publishing this site over the weekend (save for a few Flash bugs), and found it works quite easily. I don’t feel comfortable in Javascript yet, but a simple if() statement in PHP doesn’t frighten me off.

    Still have to thank Perry for a kick in the right direction though.

  74. (Perhaps suggested before, but…) Why not use a class as the replacement selector, gets round the linking issue? Even cleverer would be to use a CSS parser as with the whatever:hover fix for IE to read the font info from the stylesheet rather than hard coded in the PHP (or do this parsing on the server).

    In fact having a more generic javascript CSS parser alongside getElementBySelector would be a great toolkit for CSS techniques.

    Title

    Text

    But ideally I’d do the replacement when the content is created and embed the names of the cached images in element id’s.

    Title

    Text

  75. has anyone thought how many images you will be adding to the download time of your pages?

    A new image must be downloaded EVERY time the same words come up because it’s dynamically created.

    Why not just have images for every letter of the alphabet and replace each letter on your page with a single-character image? Users then only need download about 30 images per font size (including CAPS), and then each letter would be retrieved from the cache!
    (Not recommended for body text – but then again images aren’t recommended for ANY text!)

  76. For normal use, each of these headings will be between 1k and 3k. Placing even three or four of these on a site is not a large addition to the download time of a site. Many things in web development are a trade-off.

    Using individual characters would not work, because 1) the kerning of characters would be destroyed and 2) the ALT attributes of each image would be rendered entirely useless, making this technique unaccessible.

    I don’t think *anyone* is recommending this technique for body text. It’s simply one more option for headings.

  77. “I don’t think *anyone* is recommending this technique for body text.”

    Ah good!

    oh yes the alt text would become meaningless!

    As a header-image-generator this is an excellent tool!

    But to me it just feels wrong some how :/

  78. First of all, I love the idea and the creativity behind it.

    Quote from a previous post:

    “Now, if there was a way to define the color, font, textsize, etc in the css and use that data to create the images I could see this as a more usefull solution.”

    First of all, I think it’s a choice, whether or not to use CSS. When using replacing images, you obviously don’t think CSS is good enough to serve your needs.

    And if you do want to control your images trhough CSS, it might not require that much JS, I guess. Just from the top of my head(haven’t had the time to test this yet):

    var newEl = document.createElement(‘span’);
    newEl.className = ‘imgStyle’;
    var color = newEl.style.color;

    Or am I being silly here?

  79. I’m hoping I don’t get flamed w/ a bunch of RTFMs here but here goes…

    I have downloaded the replacement.js, layout.css and the .php file provided in the article, but how do I implement it?

    Obviously the .js and .css gets included in the head but what do I do with the .php file? Include is just like a js file with the script src tag?

    I have php 4.3.6 installed and running, but I am a CF programmer and know pretty much NOTHING about php. Can I include the php file with cfinclude?

    Also…how do I know if I have the GD graphics library? And if I don’t have it, where do I get it?

    Please forgive my “newbieness”.

  80. Allow me to thwart the RTFMs before they begin.

    It works! It took some work to get the php_gd2.dll as it is not installed by default like its said to be.

    But it’s working great. Thanks Stewart for the great article and ALA for providing such great info!

  81. It’s so amazing to observe the evolution of the idea in a creative environment. This is why I love ALA discussions.
    There is, I believe, an infinite number of ways for driving a nail into a board – starting from a hammer and working your way up to a microscope – and most of them get the work done. What to use – is entirely up to us.
    This article introduce yet another way – great. Even better, it works! Anyone wants to port it to .NET or any other platform – go right ahead, and don’t forget to share.
    Waste of bandwidth? Hard to fathom without testing under real load; I would say, it might cause some issues in some cases, but this is not the point. The point is – the more ways of skinning the cat we discuss, the larger the world population of the skinned felines will grow.
    Ewe.
    I meant it in a positive way, actually. Hmm.
    Anyway, great work, great concept, and great discussion.
    Keep it up.

    Sidetrack:
    [LazyJim] …Why not just have images for every letter of the alphabet and replace each letter on your page with a single-character image?…
    This is yet another way. And, you don’t even need PHP or any other server-side technology to implement it, you can get away with simple JavaScript: take a string of text, split it between characters, loop through the resulting array and write to the page whatever structure you wish to insert “YourArray[i].gif” image for each letter. Assuming that you have all the images pre-made and uploaded to the server.
    Here is the sample:
    http://javascript.internet.com/messages/print-line.html
    I wasn’t entirely happy with this solution, because each line of text would require numerous server trips on the first load (not only that, there was an issue with illegal characters in a file name, like ” .gif”, “?.gif”, “..gif”, etc.), so later I revised the script, using single image as a shifting background for the series of floating DIV’s and a set of CSS rules to position the background:
    http://www.gerasimenko.com
    The next iteration of the script does, in fact, dynamically replace the H1, H2, etc. tags it finds on page onload. I was going to submit a tutorial on this matter to ALA for a while, and finally did earlier this week, inspired by the article we are discussing now (I wonder if this post will be considered a “previous publication” and ALA will dismiss my submission because of that).
    Yet another way.

    [Stewart] …Using individual characters would not work, because 1) the kerning of characters would be destroyed and 2) the ALT attributes of each image would be rendered entirely useless, making this technique inaccessible…
    The kerning will be affected, yes, but not destroyed, it’s just a matter of dynamic positioning of each letter. Kerning in Photoshop is not bulletproof either, and highly typeface-dependable. The ALT attributes will make sense no more, true, but there is also TITLE you may be able to apply to the parent node element to make it up.

    [Nevel] …When using replacing images, you obviously don’t think CSS is good enough to serve your needs…
    True. It isn’t. At least not yet. This is why Stewart developed this technique in a first place.

  82. I set the font_size parameter to 14 (rather than the default 50), but the resulting images are still the same size and the type is all fuzzy. Is there another parameter I need to set somewhere?

  83. Dave: you’re running into an IE cache bug, which I have yet to solve. Even if you clear IE’s cache entirely, it still thinks the image is the original dimensions. To clear this, you’ll have to change the URL of the PHP file (i.e. rename the PHP file, and re-point the Javascript to it).

    iG.STUDiO: To my knowledge, the “title” attribute of a parent element is not an adequate substiture for the “alt” attribute of an tag. Although the “title” attribute might fix the tooltips, it won’t help with screen-readers, which is where the accessibility problem comes into play. I could be mistaken, though.

  84. This is an awesome technique in many ways. But, I would think hard before placing it on a client’s site.

    I think some clients might be unhappy with the implications of hosting a generator for images containing arbitrary text. It’s an easy way to become the butt of jokes – “hey, look, here’s a link to the Company X website that gives you an image with ‘Company X sucks!'”.

    A technically oriented person might laugh this off as clearly being speech not endorsed by Company X; after all, the text in the image is right there in the GET parameters of the URI! But imagine a client’s COO calling you up to say, “one of my staff showed me how to load a page from our website that displays an ethnic slur in a funny font. Explain yourself.”

    Unlikely, maybe, but it still makes me nervous. I’m a web-app programmer for a university, so I don’t have ‘clients’ in the sense of companies who hire me to work with their sites. But I imagine most companies would look down on any potential source of embarrasment, no matter how minor.

  85. We have been using the PHP technique at Virgin Radio for the past few years (though we’re about to change it for a slightly better technique that will enable text readers to cope too – more of which later).

    It’s fairly wasteful to get your PHP parser to make all these images every single time, and will – we found – make your webserver more stressed, especially if you’re a popular site.

    Ideally, your PHP script should make the graphics once, and then cache those graphics on the server – simply pulling those files up for display once they’ve been built once. It’s not too difficult to do, and highly recommended.

  86. what is this, a gimic to get your mark on the web

    its nothing but a IFR FIR rip off..

    i hope ALA gets a good few hundred reads from this shit

  87. And it’s called Inman Flash Replacement. Uses Flash (note, Flash) and doesn’t use server-side scripting, or PNGs, etc. This can solve different problems than IFR, and may be more flexible for some. It’s just another way to solve the same problem. The web is full of those. Pay more attention before screaming “rip-off!”

  88. I can’t seem to get this working on my host (PHP 4.3.4, GD 2.0.15)…

    GD is set up correctly (http://www.hamsterscantfly.co.uk/headertest/barcode.htm)

    The PHP script is set up not much different from the original (http://www.hamsterscantfly.co.uk/headertest/heading.php.txt – the real one is in the same directory witha normal php extension, I’m just using Arial as a test, the ttf file is in the same directory as all the files, I’ve also tried it with different fonts)

    The Javascript file is exactly the same as the original.

    But when I go to my test page… http://www.hamsterscantfly.co.uk/headertest/font.htm the images don’t show up properly…

    Anyone got any ideas what’s wrong?
    Thanks a lot,
    Tom

  89. I am you know! Things could get very silly! Weeee. Many years ago I was considering Macromedia Generator to do exactly this and now we can do it for free! Superb. 🙂

  90. Could you leave the text there and set the color to transparent so that if people copy & paste the text of your entry, the text will still appear?

  91. Derek: As far as I know, there’s no way to set text to be transparent without setting its display to “invisible”, which then makes it un-selectable.

    IFR allows text to be selectable. If that’s something you absolutely require, and accessibility isn’t your utmost concern, you might look into Shaun’s excellent method.

  92. An other solution for resizing the images:

    Give them a height or width in em, relative to the font size in the body.

    Like this they will be rescaled as well when the user enlarges the font.

  93. I see no reason why this shouldn’t work as far back as about PHP3.1 or so, as long as a recent GD lib is supported.

  94. Our Sybase EAServer webserver doesn’t know about PHP, apparently. Would it be feasible and reasonable to convert this PHP script to JSP code?

    Marvin

  95. I also think it is grat idea,but the script does not work at my server. I have the PHP 4.3.2 and GD version is 2.0.12. I don’t know I just copied the whole script, changed the font and size and it do not want to replace the text. It also do not want to generate pictures with the font. i like the idea and I want to use it but I can’t. Please help me What I have to do?

  96. This method could be implemented in JSP; possibly even easier than in PHP.

    I just threw together a quick proof-of-concept, and it wasn’t terribly difficult. The one problem is Sun’s lack of support for font kerning. Without the ability to correctly space character-pairs, font spacing looks funny. Your mileage may vary.

    I’m currently working on a repository for different versions of this technique (e.g. PHP, Java, ASP, Perl) at http://www.stewartspeak.com/dtr/ — any help in the different languages would be appreciated.

  97. If you right-click on the image, copy the URL, paste in the URL bar to only load the image, then do a shift-reload of the image it will force IE to re-calculate the dimensions. The bug is that IE caches the image dimensions separately from the browser cache (in the icon cache).

  98. i realize that another (Javan) person was asking about this – but i believe the solution suggested to him won’t help me.

    right now, i’ve got posts written by two different people, and the headings are colored differently based on the author (h3 class=daniel) or (h3 class=martha). when i apply the image replacement, it just replaces all the h3’s w/ one color… i’d like to be able to replace based on class.

  99. Daniel: The solution is pretty simple, actually. You’ll need to create two separate versions of the PHP script, for each style/color/font you wish to replace elements with. And then you’ll need to create a separate call to “replaceSelector” in your Javascript code for each of those H3 classes. For example:

    replaceSelector(“h3.martha”,”martha.php”,true);
    replaceSelector(“h3.daniel”,”daniel.php”,true);

    If you only target “h3” instead of specifying the class, it will mindlessly replace all of the H3s, using the same style.

  100. Didn’t break any new ground for me, but it’s nice to have the idea and the code explained and provided in such a way. Classic ALA article, as far as I’m concerned.

    And on an unrelated note: Stewart, I love your site’s design. Very clever and elegantly done.

  101. THis script is a revolutionary script which could save web developers many hours. It’s great.

    I have one question. My server seems not to create the images and I get the response “Error: The server could not create this heading image.” What exacly does this mean?

  102. I also have this problem on my server. on my local apache all works fine. seems like the ImageTTFBBox-function does not work on the server. but why? it has php 4.3.6 and gd 2.

    please help.
    thanks

  103. The limited number of typefaces available in web design are more than just a “dull headache.” It’s a serious enough problem almost to undermine the very notion of designing for the web. Typefaces are what ultimately distinguish printed periodicals from one another (contrast the New Yorker with Rolling Stone) and display content in a way that transcends the look of MS Word default settings. Aside from browser compatibility, I see this as one of the most important, fundamental problems web design must overcome. Fixing headlines is a start, but it’s less than a baby step.

  104. i found a solution for my problem:

    change $font_file =”font.ttf” to
    $font_file=$DOCUMENT_ROOT.”font.ttf”

    now the ImageTTFBBox-function works.

  105. I have the extensions path loaded correctly in php.ini, and I have the php_gd2.dll in there, but when I try to load the test page I get a popup on my server (running win 2k server and IIS) that says: “Unknown(): Unable to load dynamic library ‘C:PHPextensionsphp_gd2.dll’ – The specified module could not be found”

    I know it’s there, and I know the path is right, so what could be causing this?

  106. Line 89: var url = items[i].url + “?text=”+escape(tokens[k]+’ ‘)+”&selector=”+escape(items[i].selector);

    Should probably be changed to:

    Line 89: var url = items[i].url + “?text=”+escape(tokens[k]+’ ‘)+”&selector=”+encodeURIComponent(items[i].selector);

    This allows for better handling of other charsets (like UTF-8, in my case). According to the O’Reilly book, escape() has been deprecated in later versions of the spec and replaced with encodeURI(). From my testing, I found that escape encoded special characters inconsistently from browser to browser, while encodeURI worked correctly in all environments.

    Also, I added some code for retrieving the color/size/font attributes from the CSS. The reason you’d want to do this is a) in the event that a user can’t see the replacement technique, they still see appropriately styled plaintext, and b) so that you only end up specifying the headline style in one place. I think that CSS is the most appropriate place for the specification, assuming you’re already using CSS for other style information. I can post code if anyone wants to see.

    The big problem with the technique is Safari, which doesn’t support window.getComputedStyle() or element.currentStyle,*. It’s a known bug (or so I read) and will probably be fixed eventually. But in the meantime, I had to hardcode style info into the javascript for safari. If anyone can suggest another way round this problem, I’d appreciate it.

  107. Sorry. Correcting above post:

    Line 89: var url = items[i].url + “?text=”+escape(tokens[k]+’ ‘)+”&selector=”+escape(items[i].selector);

    Should probably be changed to:

    Line 89: var url = items[i].url + “?text=”+encodeURIComponent(tokens[k]+’ ‘)+”&selector=”+encodeURIComponent(items[i].selector);

  108. Does this cache the images on the server then, i.e. once one person visits the page it generates all the images, then when more people visit it sends them the existing graphics? Or is the server creating the graphics for each user?

  109. Thanks for pointing out that “escape()” is deprecated. I will update my code to use “encodeURIComponent()” instead.

    Although others have also posted the suggestion that this method should pull style information from CSS — and I myself originally considered it — I decided against it for several reasons.

    CSS is a client-side technology but this technique is primarily server-based. Although, superficially, they seem similar (both working with fonts, colors, etc), the potential for a much wider difference exists. Look at the headings on http://www.stewartspeak.com/ for an example of what I mean.

    If I pulled the font and color information from CSS, what would I gain except a little headache from the added layer of complexity? Would it be easier to maintain? Probably not: I still have to update a file every time I want to change my settings. In fact, whether I update the CSS or not, I always have to update the PHP for my more abstract settings, so now I’ve simply doubled the number of places I need to edit my styles.

    And by specifying style in CSS, I would need to build a translation table to convert the different possible font-families and styles into specific font filenames that PHP (or Java, Perl, etc) would understand.

    I understand the argument for keeping “style” in a style sheet and on the surface it makes good sense. But when you break it down, it’s merely an argument based on principle and it falls apart quickly when you consider real-world applications. There’s very little benefit for the added complexity, and so I would advocate against this method.

  110. Is there a bug in this or is there a configuration I have not seen – when I adjust the $font_size = 50 ; in the heading.php script down to say $font_size = 20 ; even if I delete the cache the png’s generated remain the same size but the become pixelated

  111. I’ve tested it with file types such as *.suit or *.ffil – yet didn’t work w/o avail. Is this only geared towards *.ttf?

    Great technique btw. So easy to implement.

  112. Chris: you’re seeing a cache bug in IE, where it maintains the original size of an image, even when that image is refreshed and changes dimensions. The only automatic fix for this issue, that I’ve found, is to change the URL of your image (your PHP filename) whenever you change the font size. That way your visitors don’t see the sizes of older headings that they’ve loaded before.

    Dru: Although the font rendering engine that PHP uses (Freetype) support mant font formats other than TTF, the image-generation library must be specifically tailored to either TTF or Postscript. In this case, for the widest audience, I chose TTF, but you could change the PHP script to use PS fonts very easily.

  113. If I set hideFlicker to true, neither the images nor the text shows.

    This technique is truly remarkable. Thank you!

  114. For the end user, how does this affect the speed of the site? I know it’s server-based, and mileage will vary, but has anyone done speed tests for this?

    Thanks! Love the technique. I’ll have to use it in one of my next projects!

  115. What if malicious people determined the path to the images and then hammered your site with calls to the heading.php program? Would there be a way to say unless the URI is not heading.php directly then generate the images?

  116. A few people have mentioned this method’s vulnerability to denial-of-service attacks. By continually producing garbage strings of text, a hacker could eventually fill up a host’s available disk space.

    There are a number of solutions, but my favorite would be to have the PHP script check how much space is currently being used by the cache. If that value rises above a certain number of megabytes, the script could email the webmaster and also stop caching images until you clear out space for it. With such a fix, flooding would still slow the server down, and prevent caching, but it would not overload a hosting accounts disk space, and images would still be sent to real visitors.

    It’s worth noting that many CMSes are probably vulnerable to similar attacks. I think I could flood a MovableType or WordPress installation with two million comments, but for most users this is a non-issue.

  117. Like this?
    http://www.stewartspeak.com/images/headings/illustrator.php?text=iG.STUDiO:%20Hi.%20This%20should%20not%20be%20allowed%20to%20happen…&selector=%23primary%20h2
    That should be blocked on the server, unless you are proud of serving your fonts to the World Wide Web – and we are down to copyright issues again – and wasting bandwidth, this time uncontrollably.
    Once again, great concept; implementation can be improved, but isn’t it always the case?

  118. Isn’t there a way to automate the detection/blocking of the domain, requesting the image? I am not profficient enough in PHP, but I believe, that many hit-counters are PHP-based, so there should be a relatively easy way of tracking a forein referrer.
    Unless you really want to monitor your image distribution personally, and possibly impair your own site by automatic interruption of service, correct me if I am wrong…

  119. This isn’t a copyright issue. I’m not breaking any laws by generating these images. Especially customized ones like those on my website. I’m not “serving fonts” I’m serving images.

    If you want to waste my bandwidth, there are better ways of doing it: I have larger files that you could continually download to blow my bandwidth cap. That’s a vulnerability of *all* small-to-midrange websites.

    Someone can use these PHP scripts to generate their own text from my website… Yes. There’s not too much I can do about that, but who really cares, either? My only concern is the security of my site from denial-of-service attacks, and I can limit that vulnerability by using the modifications I described above.

    If you’re seriously concerned about preventing people from generating bogus text (which only they will ever see), you can modify the script to check a “safe” file for allowed words. It would be trivial to get most CMSes (MovableType, WordPress, etc) to generate one of these files for you.

  120. Would really like to get some help on this…I don’t know why it throwing this error..I even check if both the ImageCreate and ImageTTFBBox are there…Please Advise

    if(!function_exists(‘ImageCreate’) || !function_exists(‘ImageTTFBBox’))
    fatal_error(‘Error: Server does not support PHP image generation’) ;

  121. I’ve followed the guide to the letter but for some damn reason the PHP file keeps spitting out an “invalid color” error. The PHP code looks perfectly fine to me, and my variables are fine:
    $text_color = ‘#000000’ ;
    $background_color = ‘#ffffff’ ;

    Help me out, this is frustrating as hell!

  122. MT: I’m not sure if you just mistyped your code, but the variable is supposed to be named “font_color”, not “text_color”.

    For others getting errors like ‘C0d3 M0nk3y’ was, I recommend taking the ‘@’ symbols out of the PHP code. These symbols, when placed in front of a function call, tell PHP to not print out its internal error messages. For testing, though, it’s valuable to see what the “real” error is.

  123. I can’t seem to get it to render a + sign, as in KTU+A. Just comes out as a space. I know the fonts I’m using has the plus sign in it. Any ideas?

  124. I had a difficult time choosing the right approach for a certain web project. The design I got was “impossible” to implement without using flash or rendering the whole page as a png. Thank you for giving me this great idea.

  125. Stewart Rosenberger: For some reason $text_color is the variable listed in the actual ALA article, but in the source code it’s $font_color… I simply copied the variable from the article 😉

    Right, so I don’t get the error anymore, and instead I get nothing. Nothing appears when I try heading.php?text=ThisIsATest

    I’m out of ideas 🙁

  126. I’m mortified! A typo! Sorry about that, MT. Glad we got it worked out, though. I hope it didn’t affect anyone else.

    But it’s still not working for you, and that’s no good. If nothing’s appearing, I would suspect maybe a Javascript bug was introduced somewhere. Depending on your browser, you could check a Javascript debug screen for any errors…

    If you want to email me for more detailed help — outside of the ALA forum — I’d be more than happy to assist you, and anyone else who needs a hand getting this method customized. You can reach me through the contact form on my website.

  127. Yes I was worried about someone filling up the server, as remote as that is. I tried sending mail when the cache folder grew above a certain size, but does that ever send a lot of mail. Instead I set it to run the fatal error script.

    I’m not much of a programmer, and my web site would probably never fall under attack like this (unless somebody wanted to prove a point specifially to me) so displaying ugly fatal errors is ok to me. But it might not do for a higher quality site.

    Again, excellent script! One for the alistapart classics for sure!

  128. I’m still looking for a way to make charachters like å ä ö look nice. I have added that extra code to line 89, but it still doesn’t help…

    Does anyone have a clue?

  129. This kind of script isn’t a real news, as far as I can remember, k10k had a script like this. I wrote a very similar script which reads all the variables from the querystring and makes it easier to change fonts, sizes, and colors “on the fly”.
    The idea of storing images in a cache folder is great.


  130. I’m not much of a programmer, and my web site would probably never fall under attack like this (unless somebody wanted to prove a point specifially to me) so displaying ugly fatal errors is ok to me. But it might not do for a higher quality site.

    You can check $_SERVER[‘HTTP_REFERER’] and verify that it matches an array of allowed domains or urls to prevent other people from using this script from other sites

  131. possible to define font size in px rather than pt, as described by article?…..

  132. Im having trouble getting it to work, just like other people in this message. in IE the text disapears and is replaced with broken link images. In Firefox however, the text comes back, as an image, but in Arial or something… just the default font.

    I also went into php.ini and uncommented out the GD library extension, and modified the extensions path, but Im still getting broken links.

    has anyone who’s had this problem found a cure yet?
    Thanks
    Mark

  133. Brian: The Opera issue, relating to how Opera handles the “innerText” property of elements, is fixed now. The fixed Javascript file is linked to below.

    Mark: You’re describing the behavior of both those browsers when they cannot download an image. The “default font” you describe is IE showing you the ALT text for the image. Check the PHP script manually to see why it isn’t generating images correctly.

    I’ve also found that replacing the “escape()” function with “encodeURIComponent()”, as suggested by will break this script in IE5(Mac/Win) because they do not support that function. So I have included that fix in the Javascript file below.

    Here is the newest version of the Javascript file, with some minor fixes (as addressed above): http://www.stewartspeak.com/dtr/replacement.js

  134. Hi,

    I was really excited by this facility. I was planning on using it for an image gallery, so the resizing of header’s text isn’t much of worry for me. Sadly, I am unable to get it working though.

    Myself and my host technician cannot understand why it isn’t working, as all files are in the same folder, and we have GD support.

    When I try to run the script by itself (http://www.poppymedia.co.uk/working/hendy/heading.php?text=hello) I get an error telling me the server couldn’t create the heading image. Oddly enough, these errors are generated as png’s using the script . . .

    Is there possibly something else that needs configuring at the server end? or in the php?

    Any help would be very much appreciated.

    Thanks.

  135. Kinda funny because I was almost ready to implement png images for text on a few of my dynamic sites, and then this article came out…

    Great job and great timing…

    Even implemented this on my blog. http://www.rynoweb.com

  136. Ah! Thanks!
    I suspected it might have something to do with those fancy free fonts, then I used the more conservative “Garamond” instead but still got the same squares… I’ll have to examine my fonts more thoroughly in the future.

  137. Thought this might help someone…

    I had everything set up properly but my server kept returning a ‘server is missing the specified font’ message.

    I tried everything discussed in this thread to no avail – then I finally realized something – the font on my PC had a tff extension that was in uppercase. I changes .tff to .TFF in header.php and now everything is working fine!

    So just remember to check the actual extension of your font file.

    Thanks for this great method. I’m sure it will gain a lot more respect once it is in common use.

  138. It’ now working on PHP4.2.2 with gd 1.6, but if i set it to use an image to each word, it appears with no space between them, and if i put one image to all the phrase, i doesn’t wrap the line….how can i solve this?
    Thank You!

  139. I’ve been having problems getting this script going right. The images show up as broken X images. Any insight is appreciated!

  140. If you’re getting server errors, or the images are not appearing at all (or as broken images, etc), you should try calling the PHP script directly.

    If this doesn’t give you a clear indication of what the problem is, open the PHP script in a text editor and remove all of the ‘@’ characters. Then try calling the script again; it should give you more descriptive error messages now.

    If you still can’t figure out how to get it to work, there is probably something slightly “off” about your server, and I would be happy to help you customize the script to your own purposes. Feel free to send me your questions ( Using this contact form : http://www.stewartspeak.com/contact/ ).

  141. I’ve done my reading on GD Library (either for actual servers or on localhost). Luckily enough – it works on my PowerBook and some servers I have.

    I know that GD Library is installed on this particular server. However, I always get the message that the image cannot be generated. I took Mr. Rosenberger’s advice to omit the ‘@’ to get the detailed error message. I’ve done so and here’s what I get:

    http://www.onlineguru.com/john/DMVOL/sample-error.gif
    http://www.onlineguru.com/john/DMVOL/heading.php – will show that heading.php does actually work because it checks that there’s no text specified. When tested, it will result as an error.

    Here is the working version with the same files uploaded to a different location:

    http://www.pingrip.com/_dru/dmvonline/
    http://www.pingrip.com/_dru/dmvonline/heading.php?text=test

  142. A brilliant technique!

    As Andy said, the volume of connections and the resources required could cause a problem on busy sites.

    What if the script stored the images in a library on disk as it created them – when requested, first check the disk for ‘URLs%20Are%20Fun.png’, and only create it on the fly if a pre-built copy isn’t available.

    This way, a contributing author could pre-build all their own headings, just by being the first to browse their new content.

    Whaddya tink?

  143. I’ve set up the text replacement, and it works fine. However, it simply outputs a series of different images, but they do not wrap.

    This question was asked on page 4 also, but no-one replied.

  144. When line-wrapping is turned on, the script will output a separate image for each word in the heading. Each of these images will be lined up, from their baselines. elements are displayed using the inline model, by default, so they will line-wrap like regular text when their container becomes too narrow to fit them all on one line.

    Is your experience different? And, if so, can you show me an example of what’s going wrong?

  145. Stewart,

    Thanks for the updated js, that corrected my error in Op7+.

    In the same message you mention a fix for IE5.2/MAC but it didn’t remair the rendering for me (http://spiralwinder.com/) on MAC. What can I try next? IE5.2/MAC isn’t displaying the text or the image.

    TIA,
    Brian

  146. There’s nothing wrong with the replacement method. The issue your having with IE5.2/Mac is that your pages is overriding the replacement function by manually setting the “onload()” function of the tag.

    Newer browsers support cleaner ways of launching code on-load, so this isn’t a problem with anything except IE5 (I think).

    My technique will piggyback on existing onload() functions, so as not to wipe them out. But it can’t prevent other functions — loaded after it — from wiping out the replacement function.

    I suggest that all pages avoid directly assigning a function to the “onload” trigger of a tag, and instead use the method that I do. It prevents us from stepping on each other’s toes when more than one script needs to be executed.

  147. Great script, Stewart. I have lot of fun with this. However, Internet Explorer behaves weird (I’m not surprised…) – my header image (another image replacement technique) is flickering.
    Firefox 0.8 and Opera 7.50 are seating quiet. I have to tweak that.

    My test: http://hostinspace.com/blog/25/

  148. I’m trying to make this work in a Microsoft Content Management System environment. Unfortunately, the page content is pulled from a database and it seems that it’s rendered after the script is loaded. The result is a normal, boring h1 style.

    Any ideas?

  149. Everything works fine, but the rendered images for the words in the Headings are always together… any ideas?

    Hello World

    Looks like: HelloWorld

    Thank you.

  150. This technique is great I have just one complaint, some of the fonts I’ve tried with it are italic and have angled strokes that go outside of the character area. This results in the generated image ending before the actual character, so characters get partially cut off. how can I tell php to make the image area slightly larger to avoid this? Add some padding if you will?

  151. wondering if anyone could shed some light on the matter…

    I found this:
    http://hotwired.lycos.com/webmonkey/99/45/index0a.html
    (there’s a link to the OVERVIEW on the left, but that page has one of those annoying install pop-ups…)

    Can anyone tell me if how this method compares to the one we read (which was an amazing article by the way!!)

    I’m still at the basic level with CSS (trying to un-learn everything ELSE I know!) but it’s ALWAYS nice to come here and see what the Big Boys and Girls are up to 🙂

    Coos

  152. Coos: That Webmonkey article is pretty old. The only modern browser to support font-embedding is IE, using Microsoft’s private format. It also doesn’t allow for any graphical effects, such as those I use on my website’s headings http://www.stewartspeak.com/

    Mattress: Although most italicized/slanted fonts should work correctly, PHP’s font library does seem to get a few of them wrong. To add the appropriate padding, you’ll have to edit a few lines of the PHP script:

    In the following lines, substitute X for the amount of padding (in pixels) you wish to use.

    Line 82, Change:

    $image = @ImageCreate(abs($box[2]-$box[0]),abs($box[5]-$dip)) ;

    To:

    $image = @ImageCreate(abs($box[2]-$box[0])+X+X,abs($box[5]-$dip)+X+X) ;

    And on line 93, Change:

    ImageTTFText($image,$font_size,0,-$box[0],abs($box[5]-$box[3])-$box[1],

    To:

    ImageTTFText($image,$font_size,0,-$box[0]+X,abs($box[5]-$box[3])-$box[1]+X,

    That should do the trick.

  153. I read this article in kind of a round about way….I had seen it on ALA but I just didn’t get what it did (didn’t read past the title) And then I stumbled on a persons wordpress blog and was amazed at the cool title fonts. Came back and read this wonderful article. Wow!

    Long story short, I finally got it working and it is soooooo wonderfully cool. now all I have to do is figure out how to get my CMS to use it.

  154. Hi, great script! Although I’ve installed on my server and it’s working using a URL such as heading.php?text=URLs%20Are%20Fun, I cannot get the script to work on my actual page using the JavaScript call in the header. I’ve created a test page with links to my source files if anyone would be so kind to see what may be wrong. Thanks!

    http://curtgranger.com/test_header.php

  155. Where you’ve written “sub2” in your javascript code, you should actuall have written “.sub2”

    The difference is that the first string targets the tag (which doesn’t exist), and the second string targets any element of the class “sub2” (which you’ve set your span to).

  156. Stewart:

    First, I can’t tell you how much this technique is going to change my life. Thank you!

    My question is about point sizes in the php files. I’ve made a test at:

    http://www.americanmicrotruck.com/replace.htm

    The first line is the replaced text. The second line is a graphic with the same font and point size specified in the php files that I made in Photoshop.

    As you can see, yours are significantly larger. I know I can muck about with the php file and get it down to the size I want, but do you have any ideas on why the sizes are so different?

  157. Hi

    Great article I allready have a .net image control that im trying to apply this technique too.

  158. GD (the PHP image library) uses the Windows-default of 96 DPI setting when it prints out text. Photoshop, by default, uses the Macintosh-default of 72 DPI. That’s where your problem lies.

    You can’t tell GD to use 72 DPI without recompiling the library, but you can adjust your own input to accomodate this difference. By multiplying the point value you pass to PHP by 0.75, you should see results that match Photoshop.

    Alternatively, you can use tell Photoshop to use 96 DPI.

  159. This is great and I got it to work a treat even with my limited php/javascript knowledge! However when I reduced the text size the new smaller image seemed to ‘stretch’ to fill the area of the old image from the larger text size. This happened even when I deleted the imgs from the temporary internet folder. The only way I could get the text to reduce was to change the text itself so new images were created. What am I doing wrong?

  160. I was reading all that stuff and I was wondering something… sorry for asking here but… 😉

    Can you replace some text with text? 🙂
    I mean to have a header and replace it’s text with other text! 🙂
    or to “split” into segments and have each one with different styles!

    ex:

    Hello World

    and through Css make “Hello” blue and “World” Red! 🙂
    ?

  161. There was some discussion about misuse of php script that generates the text by accessing it directly with a ton of random text. I was trying to think of a way to protect it and this is as close as I could get it. If you hit:

    http://genonidesign.com/dynamic/heading.php?type=headline&text=only a test

    you will be denied. If you hit

    http://genonidesign.com/dynamic/

    it will work. On the index.php page I put the following at the top:

    <?php
    session_start(); // This connects to the existing session
    session_register (“pass”); // Create a session variable called pass
    $HTTP_SESSION_VARS [“pass”] = dyna; // Set pass = dyna
    ?>

    and then on the heading.php file I added:

    session_start(); // This connects to the existing session
    if ($pass != “dyna”) {
    fatal_error(‘Error: You do not have proper access.’) ;
    }

    The problem though is that as soon as a user hits the index.php and the session has started they now have direct access to the php script itself because the session variable “pass” which is set to “dyna” stays live.

    I’m basically trying to find a way to pass a hidden variable to the php script, and this works, but once the session begins I can’t figure out how to reassign that variable after the page loads so it’s no longer valid (so they can’t load the php script on its own).

    – Tom

  162. excellent article! plus an awesome read for the 20 page comments.

    thanks for making my sunday afternoon worthwhile. 🙂

  163. I have a few comments. It is a great concept with some powerful options. But…

    First some things I can’t figure out. If I want to replace more headings, say H1 to H3, do I need 3 heading.php files? Or can it be done otherwise?
    Second, If I change the fontsize but I dont change the text the images are not regenerated. So the old image will just be resised with very poor quality as a result.
    And that brings me to the last remark. If you choose a small size for the font (like 10 to 15) the result is very bad. The spacing and kerning is not that good and so is the aliasing. Since I don’t use that much 50 pt headings in my sites it is a bit disappointing. And photoshop gives far more options for spacing, kerning, leading, etc.

    So for large fonts it’s ok. For small fonts it is an easy tool but you will have to sacrifice a lot on the quality side.

  164. Why are so many people asking for .asp versions and .cfml version of this script, just use PHP!

    PHP is free, and runs on IIS and Apache.
    If you are a professional web developer, it’s an asset to have some php knowledge. Why not start now?

  165. Stewart,

    This is a fantastic technique, and if I can implement it in Java/JSP it will save me dozens of hours of work.

    Would any version of this technique use the GD library, or would a JSP version use the Java ImageWriter libraries, or some other such? If a Java version would use GD, how would I call it from my Java code?

    I apologize if these are dumb questions. I googled around for awhile and have found no pages that compare to this thread for useful info. If anyone has any links about Java and GD, could you please post them?

    Thanks!

    OK
    DAH

  166. This is a neat idea. I’d like to figure out how to make it appear as lovely in a screen reader as it does on the screen. Home Page Reader <http://www-3.ibm.com/able/solution_offerings/hpr.html> reads each title twice. For example, “[Dynamic.][Text.][Replacement.]Dynamic Text Replacement”

    You write: “Once the HTML is finished loading, our script will search it for specified elements (

    , , etc.) and replace the text inside of them with an tag. This dynamic tag has its alt attribute set to the original text,…” It seems that for HPR, the text isn’t actually replaced with the image, HPR sees both the text and the alt-text.

    Also, a period causes speech synthesizers to pause. The periods at the end of each alt-text cause dramatic pauses between each word in a heading (unless you were purposefully going for a Shatner effect).

    There will also be a pause between each alt-text. Perhaps you could put all of the words from a heading as the value of the alt attribute of the first image and use null (alt=””) for the rest?

    Just some thoughts,
    –w

  167. My solution to the potential DOS attack issue, and accessing the script directly.

    Set a session (like Tom mentioned above) in the page calling the .js file (in index.php, or better yet, in a header file included in all the pages on your site. The session sets a timestamp, and only allows access to heading.php for a set number of seconds after it is set. The sessionid is is passed to the script, and then passed to heading.php. This configuration will work with or without cookies enabled (we have to pass the SID to the .js script, so it can pass the session id to heading.php because otherwise it won’t see the session if cookies are disabled), and will allow direct access to the heading.php script for only 30 seconds (can be increased or decreased) after the script is called from an actual page on your site.

    So after somebody loads http://www.yoursite.com/yourpage where an image replacement takes place, they will only be able to call http://www.yoursite.com/yourpage/heading.php?text=mytext for 30 seconds before it will error out, saving your site from a DOS attack, remote linkers, or people just trying to have fun 🙂 If they never hit an actual page on your site, they won’t have access to heading.php at all.

    Instructions for this modification: http://www.moonwell.com/misc/image_replacement.moonwell.txt

  168. Firefox 9.2 defaults to allow javascripts but it does not default to allow javascripts to manipulate images. If you change this in your options then this does work (albeit a little on the slow side. I don’t know what kind of server the example is running on).

    For the majority of those who use Firefox (possibly the best browser on Earth) they will not get to see this cool text replacement. JavaScript is great, but there is no guarantee that anything with JavaScript functionality will work on browser clients.

    I really like the concept of the text replacement, but is there anyway to do it without any JavaScript?

  169. For those who have followed step by step and still aren’t seeing the images being created: check that GD has FreeType support enabled. The FreeType library is required for some methods used in the PHP script (notably imagettfbbox()).

    You can tell if it’s enabled by looking at the output of . In the GD table, look for the following two values:

    FreeType Support: enabled
    FreeType Linkage: with freetype

  170. Hi,

    Great script. I liked the word wrap and flicker fixes. Why didnt I think of that! I was trying to so server side word wrapping.

    I have also been playing with image replacement using js and server side image generation using php with gd and freetype. I wrote my script about 6 months ago but then forgot about it. Only recently actually got round to using it on a site.

    I called it ImageStyle and it takes a slightly different approch. It has one file on the server. imagestyle.php and has two js files. One for the script that does the replacement in a similar way to this dynatext and another that defines the ‘image style sheet’ or iss for short. The rules in the iss are passed to the server script in the query string. The iss has a similar syntax to css and is the only files that needs to be modified. Here is an example.iss.js file.

    var imageStyleSheet = {
    h1:{
    font:’ltromatic_bold’,
    size:’24’,
    color:’002244′,
    valign:’top’,
    padding:’10’,
    height:’42’,
    background:’mytexture.png’
    },
    h3:{
    font:’KvBd’,
    size:’12’,
    color:’422f42′,
    background:’333333′,
    valign:’bottom’,
    padding:’0′,
    reload:’1′
    }

    };

    This makes it easy for designers to style pages without needing to change any php files. It also lets you define differnet iss files for different users. A standard one, another for larger text, and another for print.

    The other thing I was cooking up was direct client side cache access using the same caching key as the server side cache uses. With this the image repleacement script tries to load the image from the server side cache first and then calls imagestyle.php if it fails. This saves sever side resources.

    One more thing I want to look into is using client side flash for the image rendering server side shared font swfs. This could fall back to server side images if the user doesnt have flash.

    I’m interested in starting an open source project centered around these techniques if anyone is interested. We can work together over at sourceforge and come up with a kick arse accessible cross browser image replacement script. My only requirement is that it be done under an apache / bsd style licence, as im not keen on GPL. Anyone interested? luke@symbiosys.biz

  171. > I really like the concept of the text
    > replacement, but is there anyway to do
    > it without any JavaScript?

    Related to images, one of the most popular alternatives is the infamous Fahrner Image Replacement — but please see the corresponding ALA article by Joe Clark [1], it will explain its flaws.

    There are also several additional (and rather commendable) techniques, which are AFAIR quite good described at Stopdesign [2].

    [1] http://www.alistapart.com/articles/fir/
    [2] http://www.stopdesign.com/articles/replace_text/

  172. I have a cache folder on my localhost, do I need to set permissions on this folder? Im using OS X 10.2.8. Are my PHP GD settings incorrect or something? would be cool to get this working as it is a very cool function.

    Thanks in advance for any useful info.

  173. When I use the heading.php directly an PNG-image with the error message “Error: The Server could not create heading image” appears. So, I think the script works in some way. But the replacement for the headers don`t work.

    Any idea?
    Thanks !

  174. This is an extension to Perry Johnson’s modifications which I find more convenient. This reduces the PHP script to just one, but needs to be modified everytime a new font is added.

    The PHP script has this in the beginning instead of the hard-coded values:

    $font_type = $_GET[’font_type’];
    $font_size = $_GET[’font_size’];
    $background_color = “#”.$_GET[’background_color’];
    $font_color = “#”.$_GET[’font_color’];

    switch ($font_type) {
    case “script”:
    $font_file = “myscriptfont.ttf”;
    break;
    case “solid”:
    $font_file = “mysolidfont.ttf”;
    break;
    }

    In replacement.js, replaced this code
    replaceSelector(“h2″,”heading.php”,true);

    to

    phpfile = ‘textrepl.php’;
    for (var i = 0; i < imageHeaders.length; i++) { replaceSelector(imageHeaders[i].selector,phpfile+'?font_type='+imageHeaders[i].ftype+'&font_size='+imageHeaders[i].fsize+'&font_color='+imageHeaders[i].fcolor+'&background_color='+imageHeaders[i].fbgcolor,imageHeaders[i].wordwrap); } the javascript in the main document will have this before the link to replacement.js:

  175. Now, in terms of the concern about security (or filling the cache with unwanted files), I have the following proposed solution: assign a password to your font types. This password would be appended or prepended to your text attributes and encrypted via md5.

    So the main document javascript would be modified to :

    accordingly, replacement.js will be modified to:
    phpfile = ‘textrepl.php’;
    for (var i = 0; i < imageHeaders.length; i++) { replaceSelector(imageHeaders[i].selector,phpfile+'?font_type='+imageHeaders[i].ftype+'&font_size='+imageHeaders[i].fsize+'&font_color='+imageHeaders[i].fcolor+'&background_color='+imageHeaders[i].fbgcolor+'&pass='+imageHeaders[i].passcode,imageHeaders[i].wordwrap); } Now the following would be added to the php file : $passcodes = array("script" => “foo1”, “solid” => “foo2”); //this could be saved in an external include file

    then add
    $pass = $_GET[’pass’];

    $passhash = md5($passcodes[$font_type] . basename($font_file) . $font_size . $font_color .
    $background_color . $transparent_background . $text) ;

    if (!$pass || $pass !== $passhash) exit;

    Another php script with access restrictions could be created to determine what the passcode will be. Or if used in CMS, the passcode should be generated server-side and saved on the database.

    How easy would it be to crack this? Seems to work on my end. This method has a severe limitation, as that it will only work for wordwrap = false, because that setting does not break up the original string. Any suggestions?

  176. I just realized that the above security solution would require that every selector should match just one element, since the passcode is tied to that selector. Unless the texts are the same for each selector.

  177. i have different webspace on different servers. on one everything works just fine, on the other it doesn’t.
    it says “ERROR: The Server could not create this heading image”.

    phpinfo on that server says:
    PHP-version 4.3.1
    GD-support v.2

    any ideas?

  178. The last comment is yet another plea for help, because the script, standing alone, does not work.

    I wish to point out that someone yielded the solution above: Not only do you need PHP 4+ with GD 1.6 + installed, but the GD must also have Freetype support!

    So, if it is not working for you, use CPanel, the Terminal in Mac OS X, or whatever tool you need to recompile PHP with GD and Freetype support.

    Hopefully, that will solve things.

  179. thanks for your help, phpinfo came up with this:

    “GD Support
    enabled

    GD Version
    2.0 or higher

    FreeType Support
    enabled

    FreeType Linkage
    with freetype”

    you can see phpinfo here:
    http://boombap.net/phpinfo

    thanks in advance for any further help.

  180. I’m pritty new to css & w3c standards and the like…

    This stuff is amazing, some really talented people out there, i will definately be trying this method out on a few client sites..

    Thankyou..

  181. Well adding $DOCUMENT_ROOT. to the front of the font file bit eg $font_file=$DOCUMENT_ROOT.”font.ttf” ;
    gets rid of the “ERROR: The Server could not create this heading image”. error, but then another error “Error: The server is missing the specified font appears”

  182. Outstanding technique! I was thinking of using it for pull quotes in articles as well as in headlines, but ran across a question I haven’t seen asked anywhere else in the thread: Can multiple fonts be used in a single image?

    i.e., if I want to generate a small block of text where all elements are in #ABABAB Myriad Pro *except* for one or two words in #7B001A Myriad Black, then is there a way to map the or tag to that other font and color?

    Many thanks again for both the technique and any light you can shed on this question!

    Greg

  183. How hard would it be to adapt this technique to create static images for a web site that could be uploaded manually and magically drop into place, giving the same look, but having none of the dynamic caching issues to worry about?

  184. I am trying to use Perry Johnson’s modifications, it works fine in Firefox, but I am getting an error in IE “imageHeaders[i].selector in not an object”.
    Is anybody getting the same?

    Great script btw!

  185. Many thanks for this text! I didn’t know of this possibility and also I don’t have any use for it now I find this technique very interesting.

  186. What about using downloadable fonts? As far as I know, the @font-face {src: something;} declaration still works, and will download any truetype font from the server to use to render the page. Is this approach not recommended for some reason?

  187. Like someone mentioned way back there, you can use the HTTP_REFERER variable to supply dynamic text to your site only. I put this near the top of heading.php:

    if ( !isset($_SERVER[‘HTTP_REFERER’])
    || strpos($_SERVER[‘HTTP_REFERER’],
    DOMAIN_NAME) === false ) {

    header(‘HTTP/1.0 404 Not Found’);
    exit;
    }

    where DOMAIN_NAME is a constant defined elsewhere in an include (eg = http://www.mysite.net). Turn referrer logging off in Opera and you get no images, but I don’t know of any browsers that do this as standard; does anyone else know better?

    Also, this comes up with a blank page rather than a 404 Not Found page if I access it directly from any browser other than MSIE, is there any way to force the server to show its own 404 page for all browsers?

    Joel> I think only MS Internet Explorer understands downloadable fonts. You obviously haven’t read the previous 22 pages of discussion…

  188. I think the problem with this approach is that the http referer is supplied by the user agent. This means that a successful DoS attack is still possible by simply having the DoS program supply an http referer equal to what your script expects.

  189. Yes, that’s true. And if the pattern matching isn’t anchored to the left of the referrer string (as in my example above) it’s even easier because you can just add “?http://www.yourdtrsite.com” to the end of the referring site. It would probably deter an idle miscreant though.

  190. Really great little script. Some advice culled from various places:

    use MS VOLT to convert TTF’s to Open format;
    place the TTF in the root of your webdir;
    HEADING.PHP: I had problems with the location of the TTF until I used this:
    $_SERVER[“DOCUMENT_ROOT”].’/thefont.ttf’ (don’t forget the slash in front of the font);

    Everything else works as advertised. Great job!

  191. I am using this script on my webpage, and I set the cache directory to ‘cache’.

    I can’t seem to find a cache folder on my server with the images in them. I tried specifying an absolute non-relative path, and that didn’t change anything. I added some debugging code in there, so I’m sure that it’s always creating the image on the fly. I tried removing all the @s to check for other errors that might be generated, and nothing. It works perfectly, except that it doesn’t create any image files.

    The script lives at http://isaacschlueter.com/skins/isaac/_heading-side-sub-title.php?text=No2menR!(on%20fire)

    So, would the cached images be in
    http://isaacschlueter.com/skins/isaac/cache/
    or in
    http://isaacschlueter.com/cache/
    Or somewhere else entirely?

    Both folders exist and are chmoded 775.

    Any ideas out there in alaland? Something I’m missing? Thanks 🙂

  192. Here’s how I got it to cache the images properly:
    1. Create a folder called “cache” which was in the same folder as the dtr php script.
    2. chmod that folder 777
    3. Set the $cache_folder = dirname(__FILE__).’/cache’;

    The load time goes down when it’s pulling a cached image, making the brief flash less noticeable.

  193. I had the same problem as Catherine, from 11 July 2004 @ 7:32am. When you change the font size, you have to recreate your header text, otherwise IE will stretch the image to the original height, even if you clear the cache, etc.

    Also, it is so slow to load, that in Netscape shows two broken image tags initially, which are then replaced by the images.

    I’m excited about this code, but with the 2nd problem especially I’m afraid to implement.

  194. Has anyone found a solution to the image display as an x-out on IE and displaying only the alternate text on mozilla?

    More info: The image creation is working great, it’s sitting there in the cache folder, and can be called by accessing the URL directly – mydomain.com/md5crypt_of_image.png

    But it won’t display when called directly from header.php on IE or Mozilla

    Have tried on a unix server and windows. When creating the image directly from the header.php script my local server is saying: The image “http://127.0.0.1/imagetest/header.php?text=test%20&selector=h2” cannot be displayed, because it contains errors

    But again the image is being created and stored in the cache folder.

    PHP v > 4.3
    GD2

    Anyone hit the same wall?

    Thanks!

  195. Hi,

    A page with text replacement on it does not seem to finish loading when you view the page in Firefox 1.0 – you get the message “Transferring data from domainname” in the status bar rather than “Done”… is there anything that can be done to fix this?

    Works fine in IE

    James

  196. Fantastic stuff Stewart, thanks for sharing! Is there any way to adjust the wrapped line height (say, by vertically padding out the images). Also, this is probably a related issue, is there any way to refer to the images in the page by class or id so I could for example include or omit them from css img rules governing the rest of the page, could this be added to the js file? I know little of php or javascript so any assistance is much appreciated 🙂

  197. I can’t seem to make this script work. I downloaded the complete script and saved it as h1.php (http://phpmor.ceep.dk/h1.php) and copied the font to the same folder, but it’s not working! Try for instance typing http://phpmor.ceep.dk/h1.php?text=hello, nothing.
    The only thing I’ve specified in the script is the first part

    $font_file = ‘absalom.ttf’ ;
    $font_size = 60 ;
    $font_color = ‘#000000’ ;
    $background_color = ‘#ffffff’ ;
    $transparent_background = true ;
    $cache_images = true ;
    $cache_folder = ‘cache’ ;

    Does anyone have an idea of what might be wrong?

    Thank you,

  198. Hi,
    I use alternate stylesheets on my site, and I’d like to use text replacement on only one specific alternate stylesheet.

    Anyone any idea, how this could be done?

  199. My box is linux rh 9
    I tried several fonts, including importing fonts from windows.

    Still cant settle the transformation from Hebrew text to images, only show as square images.

    Is there anyway I can get around this?
    Thanks

  200. See this page:

    http://www.whaleofadive.com/test.php

    DTR works as it should.

    Now let’s serve up the page as application/xhtml+xml thru the HTTP headers:

    if (isset($_SERVER[“HTTP_ACCEPT”]) && stristr($_SERVER[“HTTP_ACCEPT”], ‘application/xhtml+xml’)) {
    header(‘Content-Type: application/xhtml+xml; charset=ISO-8859-1’);
    }
    else {
    header(‘Content-Type: text/html; charset=ISO-8859-1’);
    }

    Look what we have:

    http://www.whaleofadive.com/test2.php

    If you’re using IE, you get the same result. But Firefox doesn’t display the transformed text in the second example. Is there a way around this?

  201. My ISP’s server has PHP 4.3.x, but I don’t know whether it has version 1.6 or higher of the the GD Graphics libarary.

    heading.php passes the @ImageCreate test, but goes no further than the call to @ImageTTFBBox.

    Is this just an indication that I don’t have the right version of GD Graphics? If so, shouldn’t this test be included at the beginning of heading.php?

    I have submitted an email to my ISP, but wondered if any of you know this answer.

    Your help is much appreciated.

  202. After my ISP told me that phpinfo() does not produce the correct results on the server my account is mounted on but that indeed the server the PHP runs on is 4.3.x and GD is 2.x and FreeType is enabled.

    Essentially, nothing appears on the screen (no error messages) and code stops after the call to @ImageTTFBBox.

    I am using the MIME types in the example here, sticking close to it until I see results. RegEx, is your code my solution?

    Also tried this possible solution from “matze”:
    change $font_file =”font.ttf” to
    $font_file=$DOCUMENT_ROOT.”font.ttf”
    When I substituted my font file this only resulted in the script not finding my font which it has been finding just fine.

    Also tried replacing
    $cache_folder = ‘cache’ ;
    with
    $cache_folder = dirname(__FILE__).’/cache’;
    as suggested on a PHP list.

    Helllp!

  203. [QUOTE]
    my ISP told me that phpinfo() does not produce the correct results on the server my account is mounted on
    [/QUOTE]

    What the heck…?

    As for the MIME type, have you tried testing the script without sending HTTP headers or doing any browser sniffing, etc? Also, any chance you can give us a link to your test page?

  204. My demo is at:
    http://www.synprod.com/imagereplace/demo.html

    RegEx, I tool out the HTTP headers in demo.html as you suggested and I still don’t get the images.

    My only change to the Javascript file in Stewart’s example was to add:
    replaceSelector(“h1″,”heading.php”,true);
    since only “h2” was covered.

    “heading.php” is as in Stewart’s example.

    I made a few test changes to see if I could correct the problem, but restored all of them.

    As far as the phpinfo() goes, I can only offer this response from Speakeasy, my ISP:

    “Running phpinfo on grace [my server] will not give you the correct results. Our webcluster, where you go to upload your files, is simply a mount point on grace, grace is not the webserver. If you could run phpinfo from a web interface on our servers, that would give you accurate results.

    Our GD library does have FreeType enabled, and the version of PHP the webservers are using is 4.3.x.”

    Thanks for your help and for anyone else who might have a suggestion on how to proceed.

  205. Synergy, I think the script is working on your test page, except the images have the ‘text/html’ MIME type. Weird. Are you sure you left $mime-type in heading.php as image/png?

  206. I checked and I left my MIME type as image/png.

    Again, I appreciate your help with any suggestions that might break through this.

    RegEx (or anyone else), I would be happy to email my files if that might enable you to see directly what might be amiss.

  207. Hey guys, do you mind addressing questions about implementation of DTR? A wonk at b2evo suggested I give it a whirl because I want to display text in an Ancient Greek font complete with accents and other unusual diacritical marks. So I followed the instructions and it ALMOST works–the swapout happens, and I get a PERFECT “alt” text, but the image doesn’t load–just an image placeholder, with a little bar for every character that should be there. Any thoughts?

    Thanks.

    mikeyboy

  208. Ok, I hate not being able to figure things out for myself, so I read the article again–my server probably lacks support fot the GD graphics library. I don’t yet even really know what that means–I’ve got their website open in another browser window right now to try to figure it out, and then I will go to my hosting service (the much-maligned Hostdime) and see what they have to say about GD graphics library support).

    Think I’m on the right track?

    Thanks again.

    mikeyboy

  209. I really liked this article and have found it really usefull. One problem I have found when putting it into practice is that the word spacing can not be controlled. Does anyone know how this could be done?

  210. Sorry for being rather remedial, but can anyone help with the syntax of using a class in the replaceSelector(“span”,”fontconvert.php”,true);
    line, i.e. if I want to replace only span class=”fancy” or something. Thanks.

  211. Use CSS selectors. For a span with class “fancy” use:

    replaceSelector(“span .fancy”,”fontconvert.php”,true);

    There’s a space between span and .fancy. I reccommend Eric Meyer’s “Cascading Style Sheets: the definitive guide” to you for learning about CSS. It’s a great reference on CSS 1 and 2.

  212. Thanks very much for the syntax help. I have the book you recommended, though more often I use Meyer’s CSS 2.0 Programmer’s Reference.

    Thanks again.

  213. I keep getting this error

    “Error: No Text Specified”

    I have the

    tags in my document to be replaced but it wont work. What am i missing?

  214. I found I had to write it withOUT the space for it to work.

    replaceSelector(“span.fancy”,”fontconvert.php”,true);

  215. This is a very interesting notion from my point of view, I am building a web site on obscure Fonts. I have tried to follow your (great) tutorial as closely as possible, but it didn’t work for me. Here is the page

    http://www.osop.org/textrep.htm

    Can any one tell from here whats going wrong???

    Thanks in advance John Maillard

  216. I really like this, and have used it on a site of mine…had one problem though:

    When I changed the text-size in the .php file and refreshed in IE, the image stayed the same size and the font went all pixely. This doesn’t happen in Firefox. This continued to happen after I deleted all my temporary internet files etc.

    Anyone else encounter this, or know whats happening?

  217. Great script. Discovered it only yesterday.
    First time I did something with PHP. Well.. did something… copied it and used other values. That’s it.
    It workes and I’m impressed.

    I had the idea to copy the fonts to a directory above root like common with databases. You don’t want to distribute your fonts. You just want to use them. So you don’t want the visitors to download them.

    For example you have the following 3 direcories on your ftp site.
    database – well it says it all
    www – the root directory of the website, here are the htm’s, asp’s, php’s and everything
    fonts – the font directory, available for the scripts but not for visitors of the site

    Is it easy to adjust the php script to use that dir? Should be, I guess, but I don’t know anything about php yet.

    And is are there scripts online with all improvements discussed before included?
    I mean the security issues and easy maintanance improvements like just one php script instead of one for every variation.

    Marcel

  218. I managed to get a simple demo working in less than an hour. Pretty good for someone like me who’s just a hack at JavaScript and knows slightly more than zero about PHP.

    http://darrenwilson.com/test_tube/dynamic_text/

    I don’t know if it’s my font selection (I just used some freeware TTF fonts i had on my machine… most of my fonts are PostScript) but i’m experiencing some odd word spacing problems. Is this due to font selection or some other issue?

  219. After reading some of the previous discussion, i confirmed that the problem i’m experiencing with word spacing issues is entirely related to having word wrapping set to “true.” Turning off word wrapping makes everything space nicely.

    Has anybody come up with a solution that will allow word wrapping but preserve proper word spacing?

  220. Hi Stewart,
    I really appreciate your downtime – your earned it for that article alone >;o)

    Anyway I need help on this promising solution, maybe somebody else could have a look at my files.

    This is the problem:
    To call the script directly with
    http://www.crimeZZZ.net/demo/h1.php?text=eliZZZa
    works fine and produces the cache image.
    Called via the test page
    http://www.crimeZZZ.net/demo/demo.htm
    does not show anything and does not generate a cached image.
    The rest of the files named as in Stewart´s example.

    Up to now I checked the following:
    * Requested support from my provider – everything okay from his point
    * Tested in various browsers – same result

    I really don´t see the error – what am I missing???

    Great thanks for any help
    eliZZZa from Austria

  221. Hello Stewart, your script and your idea are absolutely awesome! A great way to make use of PHP’s powerful features.

    Unfortunately I was unable to make it work and since this (posting a comment here) seems to be the only way to get some kind of support (hopefully you’ll have a support forum at your new site) I thought I’d give it a try because I would really like to use it.

    I am using FireFox (Mozilla 1.7.3). My Apache server has PHP version 4.3.8 with GD enabled (it says version: bundled 2.0.23 compatible) and PNG support enabled. So I think I meet the requirements, don’t I?

    As far as settings I can’t see how I could have done anything wrong…

    I have looked at your on-line demo and copied your settings as a last try but I still don’t get anything.
    I have copied the test.png file to the same folder where the other files are and I have copied your entire replacement.js file to make sure it’s all the same as in your demo. I have named my PHP file h2.php and inside it I have set the path of the font to: ‘/home/username/domains/chaindlk.com/public_html/sources/text-replacement/JaggedDreams.ttf’
    (in this URL I have replaced my username with the word “username” for privacy). I know for sure that this is the correct path because:
    1. I have looked it up in the server’s documentation
    2. I have this path on a CGI file I am using and it works
    3. if I change the path your script gives me a “font missing” error, but with this path I simply don’t get anything at all

    I have also tried using absolute URLs (even though the articles instructs to use the path and not the url).

    As for fonts I have tried 5 different ones to make sure it wasn’t an issue with the font.
    I have tried:
    prefix.ttf
    lydianv.ttf
    JaggedDreams.ttf
    and then I thought of trying the OTF ones and went to http://freefonts.fateback.com where I have downloaded:
    JaggedDreams.otf
    JungleBurnout.otf

    Basically I don’t know what else to try.
    I have troubleshooted this as good as I could.

    Here is the link:
    http://www.chaindlk.com/sources/text-replacement/h2.php?text=test

    What else can I try?

    Also, if I ever get it to work (hopefully somebody will help me here) I have one question:
    is it safe to assume that on an apache server I can set $cache_folder to ‘var’ because (as far as I have read) that is Apache’s temporary files directory. If this is not correct and I leave it set to ‘cache’, would I have to create the directory inside the folder where all the files reside or would I need to create it in the root and give it a path (or an url)? Also would I need to chmod it to 777?

    I hope somebody will be able to answer my questions and make this gorgeous script work for me as well!

    Thanks

  222. I think I have figured out that this will NOT work unless the server has the TTF library support (FreeType library from freetype.org). Is this correct? Can somebody let me know? Thanks

  223. works great, but i have one big problem. when i work with text in tables the m$ internet explorer doesn´t makes a word warp.

    in firefox the word warp works, but there the script has problems with image generated numbers like “6.”

    outside of any tables, the word warp works also in ms ie…

    for example:
    http://www.joerg-wikinger.de/example.html

  224. The test.png was uploaded in wrong format (ASCII instead of binary) – that´s why it did not work.

    I am delighted by your solution!!!
    eliZZZa

  225. Trust me I understand, I use php and have for years so I talk till I’m blue in the face about how great it is, however the flipside to this coin is some companies are so M$ brainwashed that anything but asp or likewise technologies are shunned no matter how many advantages you can prove with your favorite language. I’m a php programmer in the heart, but alas, my shop forces me to write asp to earn the paycheck…

  226. discovering this technique has really saved me a lot of time. I have been playing with it a bit today and am trying to find out if anyone has either of these two problems.
    1. I have several different span classes set to trigger the text replacement.
    for example-
    span.heading
    span.big
    etc.
    when I have checked the results in ie6 it only changes the first span.class it sees and the rest of them just come up as the normally formatted span.
    and
    2. in netscape 6 it does recognise every span.class listed and change to the new font but when the normally formatted span is viewed without the php/js links, it comes up with no space at all between words.
    the site in question is viewable at
    http://www.thepeartreeofbrookline.com
    thanks.

  227. Please help me get past “Error: The server could not create this heading image.”

    First off, here is the phpinfo:
    http://www.hai.org/imagereplace/info.php
    It seems to have all the FreeType support, GD version, etc. that is required.

    I am definitely passing the test of finding the font, but, since others who have had this problem have suggested it, I tried the following variations for $font_file:

    1. absolute address
    2. All the variations of document root addressing that have been mentioned in this discussion so far.

    The ONLY changes I have to the heading.php that Stuart provided is the name/location of the font and a font size of 36.

    I have traced the error to occurring with the call to @ImageTTFBBox but the discussions of that here have provided no answers. Stuart? Someone, please help. I have spent way too much time on this without finding a solution.

  228. first i want say that this technique is great.

    i have a question about this:
    Stewart Rosenberger says at the the end of the article »… although getting rollovers to work would require more customization.«

    ist here any way to do rollovers? for examble to change the fontcolor on hover.

    would be perfect!

  229. Problem with this approach is that you can only use ttf fonts, not adobe fonts (I know this for a fact with ASP.NET and C#, and from what Ive gathered it is hard if not impossible to try to convert them to ttf; the software for that stuff is supposedely really expensive).

    I dont know about you guys, but all my fonts are adobe fonts.. You can use a similar approach with flash if you need more than just ttf fonts..

    The cool thing about using flash is that the swf is loaded once, then it can be used for your entire site since its cached.. The bad thing is that support for flash is sometimes questionable.. I go around this by just showing a crappy arial/tahoma/verdana H1-H6 heading whenever the user doesnt have it, and it works out fine.

    Check this link out… this is where I first saw it.

    http://sports.espn.go.com/nhl/news/story?id=1715637&partnersite=espn

    Here, look at the headline, its all in flash and the headline gets passed in as a querystring in the object/embedd tag.

  230. Works like a charm but when navigating with browser buttons, dtr seems to replicate with no way of stopping… only on mac versions of IE 5.0+
    Anyone else getting/seeing this bug?

    Thanks.

  231. Sir, i just want a help from you that, could we make a text written on uppper side and lower side of image dynamically. If we insert a text from a textfiled called Upper side and other text from a textfield called “Lower side”. I want that the text enter in Upper side textfiled goes automatically at the upper side of image and same for lower side textfield , could it be possible from Javascript.

    Please look an example given at Url:
    http://www.ringcompany.com/designcenter.html

    Click on the right side image. Apopup will open.

    Insert username=amitk
    Password=weblink

    Click on saved design.

    Then click on the link “new1_25_11_04” provided below the link of “Design Name”

    This will show you the details of product. Click on next step.

    Click on Edit.

    This is the example of what i am taling about.

    Enter any text in Upper: or Lower textfields.

    This will show you on image at runtime.

    Please tell me that it is possible in PHP or Possible in Javascript.

    Early reply will be appreciated.

    I trust your site very much.

    Please reply soon.

  232. This caught my eye.

    After trying Shaun Inman’s IFR and injuring myself by the number of problems and lack of support, this script looks promising.

    But a few questions:
    1- How would I be able to get an image to occur in the output?
    (eg: a dotted line automatically to be inserted underneath the outputted image text)

    2- Can you change the case?
    (eg: Original text would be normal case, but final image should all be uppercase)

    If these problems can be ironed out then it would be a perfect script.

    Support welcome, Matthew.

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA