Click here to Skip to main content
Click here to Skip to main content

Using custom fonts with dynamic headings

, 16 Sep 2007
Rate this:
Please Sign up or sign in to vote.
Use this control to create dynamic headings on your webpages so you can use custom fonts without needing a designer everytime you want to change a heading!

Screenshot - main_image.png

Background

At the web agency I work at, it is important that when a designer is laying up a site, they are not held back by the limitations of HTML. Of course, at the same time, the technical team still needs to produce an accessible website in HTML! One of the classic design limitations has always been the varying ability to embed non-standard fonts. Mainstream browsers have had the ability to embed fonts since IE4 and Netscape 3.5, but this support has been non-standard, ad-hoc, and inconsistent. As such, there is no easy way to achieve cross-browser and cross-platform font embedding. This restricts designers to either using Verdana, Arial, and Helvetica with Sans-serif as the fallback, or having to produce multitudes of images - one for every heading. Of course, this increases maintenance costs when your client wants to change or add a heading as you need to get a designer to fire-up Photoshop just for, effectively, a text amend. In aid of simple maintenance, we wrote this dynamic headings control.

Using the code

The whole purpose of this control is to make things simple so once you have completed the configuration, the page usage should be trivial. This is an example of the usage:

<tm:dynamicheading id="Dynamicheading1"
   text="Skulls are cool" 
   headingstyle="skulls" 
   runat="server" />

We've registered the control in our page (or you could globally register it in the web.config) with the prefix "tm", and we've created a style in the web.config, as shown below.

 <dynamicHeadings>
    <fonts>
     <font name="Calaveras" 
       location="C:\Projects\Article\DynamicHeadings\font\CALAVERA.ttf" />
    </fonts>
    <styles>
        <style name="skulls" 
            foreColor="Red" 
            backgroundColor="Transparent" 
            padding="0 0"
            fontName="Calaveras"
            fontSize="36px"
            fontStyle=""
            />
   </styles>
</dynamicHeadings>

As you can see, we've registered a font here and then created a style that uses this font. The name of the style we have used is the one used in the headingstyle attribute of the web control. The name attribute in the font element should be the name of the font you are using. This is not the name of the font file, but rather the actual name, which you can find out by opening the font in a font viewer (this must be exactly as shown, otherwise it won't work).

You can register as many fonts and as many styles as you want, and you can use these as many times as you want on a page via a control. I've tried to make the options as close to that of CSS as possible without making it confusing. I've also added the ability to set a heading level so that heading tags will also be rendered on the page.

How it works

Here is the output generated from the above configuration:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>Skulls heading example</title>
</head>
<body>
    <form name="form1" method="post" action="default.aspx" id="form1">
    <img alt="Skulls are cool" 
      src="http://www.codeproject.com/images/headers/skulls/Skulls%20are%20cool.aspx" />
    </form>
</body>
</html>

As you can see, an image tag is created and the alt text is populated with the requested text. The alt text will always exist and be the text used in the text attribute (this erases the possibility of copy and paste errors where the text doesn't match the image). All of the information required to generate the image is in the URL. The text for the image is stored between the last "/" and the ".aspx", and the folder name before that is the style to be used.

The page is created in one request, and then requests for these image files are handled by an HTTP handler also registered in the web.config. This handler splits out the style and text, then requests the style from the style store. Using the style details, an image is then generated and returned to the browser.

The code

I hate doing things twice, and to me, that is one of the attractions of programming: to do something once, properly, and then use it again and again. As such, I didn't want the fonts to be loaded again for each image request, so I needed some level of persistence. I could have used the cache, but instead went for a singleton which contained the font and styles, which I've called StyleStore. The constructor of StyleStore loads up the fonts and styles, and because static classes are stored in the application level, this will only occur once for each application. Any time a new font or style is added, the application is restarted, so this will cause the fonts and styles to be reloaded as well.

Other than this, the code is not terribly difficult to follow. The image rendering can be found in many examples across the net and CodeProject. The control is a fairly standard web control, although I've steered away from using the viewstate for simplicity' sake (and personal preference).

I decided to throw as few exceptions as possible because hopefully the system will be easy enough to configure for users. Also, configuration exceptions aren't the easiest to track. If you get black on white Verdana images, then you have configured something wrong; you will, however, get an exception of "no font file found" if the location specified is wrong.

I've also implemented custom configuration sections with collections, if you are looking for an example of how to use this nice feature.

Getting the example going

You will need to have the ASP.NET web application projects update installed to use the provided project file (free Microsoft download). Once you have that, you will need to set up a virtual directory and point it to the file you've unzipped to. Open the web.config file and change the font directory paths as appropriate. The four fonts provided are available free from 1001 free fonts.

Accessibility

In an ideal web world, all content would be text, which would allow for unlimited end user customisation. In light of the inability of web browsers to embed custom fonts and the limited array of web safe fonts, this control fills the gap between ease of maintenance, designer and client demands for prettier sites, and web accessibility through the dynamic generation of image headings with enforced alternate text and optional heading tags.

License

Trunk Media retains the copyright of this article and code. The code is licensed under the Lesser General Public License (LGPL), which means you can use the library to create your headings by linking to it. It'd be nice if you link to our site if you do. As I understand the LGPL, you can also recompile the code and add or remove any features you want or don't want, or fix bugs, as long as you release the code back to the community and retain the copyright headings in the code.

Limitations

  • The custom configuration section uses features of ASP.NET 2.0, so it isn't easily backwards compatible to 1.1
  • There is no text-wrapping ability, although this could be added without too much difficulty.
  • The GDI way of measuring fonts, especially custom fonts, is not terribly accurate. I've achieved satisfactory results by adjusting the padding on each style (you can use negative padding).
  • The images that are created are PNGs, this is so that we can use transparencies easily, and because they are a nice, open standard image format. You may need to incorporate the PNG fix for transparencies if you are building for IE6.
  • Images are not currently being cached, which would be essential on a high hit website.
  • Font sizes aren't necessarily consistent across fonts. Check sizing in a font viewer first, or just play around; this is due to font design, not a limitation of the code.
  • There is currently no way of constraining the image dimension. This could also be added without a lot of difficulty.
  • No background images, but again, this could be added.

Future improvements

With the addition of the caching functionality, it would now be possible to generate a unique key for each unique image, which could be used instead of passing the style and text values in the URL string. This would also facilitate the other feature I'd like to implement, which is writing the images to the hard drive and then referencing them through the web server directly. Stay tuned, or feel free to contribute.

Summary

In light of the short comings of browsers and fonts, this control has been designed to allow users to create image replacements which are easily configurable and have the additional benefit of protecting the font copyright holder. Check out the example project, and hopefully this will better explain the features and abilities of this control. I appreciate all constructive feedback.

History

  • 17 September: Version 1.2 - Added the config checking page. This is accessible from the HTTP handler folder + "/dynamicheadings/checkconfig.aspx". This will print out any errors that have occurred in the processing of the web config section.
  • 24 April: Version 1.1 - Added simple caching, made the exception serializable, added in a string length limitation default (which is adjustable), and added a settings class for control wide settings. Thanks for the feedback Ramon and Kevin.
  • 23 April: Version 1.0 - Enjoy!

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)

About the Author

Scott.Mayo
Web Developer
New Zealand New Zealand
I'm currently technical director at Trunk Media, an Auckland,New Zealand based interactive web agency specialising in accessible and usable web development. I've had several years experience working in London,England working for a top web agency whose clients included several FTSE 100 companies. I've been developing websites for over 8 years now and have a broad range of skills I'm constantly trying to improve.
 
When I'm not flat out at work I'll be cross country mountain biking, trying to snowboard, swimming in the surf or fiddling with an old car or two.

Comments and Discussions

 
GeneralAbout downloadded code Pinmemberdanishshamshad0074-Feb-11 23:25 
GeneralIIS7 web.config PinmemberA4Andre18-Nov-08 7:35 
GeneralRe: IIS7 web.config PinmemberScott.Mayo18-Nov-08 10:27 
GeneralRe: IIS7 web.config Pinmembermsallaty13-May-11 15:42 
GeneralRe: IIS7 web.config PinmemberLucio Flavio20-Dec-12 17:28 
GeneralVersion Pinmemberzimzimmer29-Oct-08 3:09 
AnswerRe: Version PinmemberScott.Mayo29-Oct-08 10:56 
GeneralRe: Version Pinmemberzimzimmer29-Oct-08 23:49 
QuestionProblems with location Pinmembermaverjk9-Mar-08 1:42 
GeneralRe: Problems with location PinmemberScott.Mayo9-Mar-08 10:49 
QuestionIE6 and png fix Pinmemberjpye27-Nov-07 10:13 
AnswerRe: IE6 and png fix Pinmembertoxaq27-Nov-07 10:31 
QuestionRe: IE6 and png fix Pinmemberjpye28-Nov-07 8:06 
GeneralCode Requirements Pinmembersmm2513-Sep-07 11:53 
GeneralRe: Code Requirements PinmemberScott.Mayo13-Sep-07 12:18 
GeneralRe: Code Requirements Pinmembersmm2513-Sep-07 19:54 
GeneralRe: Code Requirements PinmemberScott.Mayo16-Sep-07 15:25 
GeneralStandards and accessibility PinmemberRamon Smits22-Apr-07 22:29 
GeneralRe: Standards and accessibility PinmemberKevin Darty23-Apr-07 2:31 
GeneralRe: Standards and accessibility PinmemberScott.Mayo23-Apr-07 11:14 
AnswerRe: Standards and accessibility PinmemberScott.Mayo23-Apr-07 11:07 
Hi Ramon,
 
Thanks for you feedback. To cover off your points:
1) Firstly, the alt tag is rendered and it is rendered exactly as the text that is entered. I've been building accessible sites for about the last 5 years but sometimes clients and designers really want that special font for whatever reason. Personally I'm pretty happy with verdana and arial as they're both easy to read. One of the problems I've noticed with maintenance on large sites is that people get sloppy when copy and pasting image headings and using this technique prevents any possibility of having the wrong alt text matched up to the image wording which makes for a true accessibility nightmare.
2) I like the idea of a javascript option but I don't agree that the document doesn't comply with standards. I don't think you will find anywhere that says that you cannot use images for headings, they just need to have alt text (which this control enforces) and you need to wrap the image in the appropriate heading tag (which is optional in this control with the headingLevel attribute). This control also allows you to pass in class and style attributes to the heading tag if need be.
3) I agree that dynamically creating headings is not ideal but as I stated in the limitations the system is not yet cached but I felt it was important to put something out there for the community and improve on it with feedback, time limitations.
4) Try catch was kept generic as I wasn't passing on any of the exceptions. You either got it right or you didn't. I found this was an easier of ensuring you always got something out of the pages.
5) Rendering 1000 characters. Again, I put this in my limitations and it would be trivial to implement to put a maximum of 100 characters or less but I thought I might wait for some more inspiration or suggestions on the cleanest way of dealing with this.
6) I don't think referrer checks are a particularly useful way of dealing with bandwith stealing or cpu stealing. Any sort of caching or writing images to the hard drive would make this unnecessary (although bandwidth stealing is always a problem on any big site and there are many ways of dealing with this).
7) Font size was the first thing I implemented. What were you referring to here?
8) File based cache is mentioned in the limitations and I will be implementing this as time allows. I personally wanted the option in the configuration of writing to disk and serving from there or cache depending on preferences.
 
As my company dedicated some time to give back to the community that we use so often time was limited on this article, hence the list of limitations. I hope that this technique, which is certainly useful, will help others in a similar predicament.
 
Thanks for your feedback. I'll be looking into why exceptions should be serializable. Initially I was throwing alot more exceptions but cut this down for practical purposes and I was close to deleting the exception class. Did you install the code? Was it easy to configure and use?
 
Cheers,
Scott.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140709.1 | Last Updated 16 Sep 2007
Article Copyright 2007 by Scott.Mayo
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid