Thoughts on Embedding Fonts In Web Pages & Navigational Menus
I'm working on a little web interface for a friend that involves the use of a specific font for the navigation menu items. So far, I've have been a good little developer and have kept everything neat and tidy. The html contains just html with imported style sheets and I have eschewed using javascript by positioning everything with CSS. I can get away with it as a conscious decision was made to ignore IE6 and conform to standards (at least insomuch as the standards are implemented in IE7+, FF3+, and Chrome (assuming that means all webkit browsers & I'll test to make sure that it looks OK in AIR applications too) ).
But fonts are a pain. The friend is a designer, the font WILL be used. That leaves embedding graphics, sIFR, prepackaged Flash or custom Flash. Custom Flash is last because that is what I used, but I will dispatch with the other options as quickly as I can. (There is the @font-face; MS has an IE only font embedding scheme, *.eot files, and FF3.5 will support embedding TTFs but neither is presently practical for wide use.)
Graphics
Actually, as weird as it seems, this did seem like a tenable option to me. I was even prepared to build a library of gif characters to allow for flexibility in future menu changes. But what if the font decision were to change? What if I had to endure crazy styling concerns and found myself tweaking the placement of several dozen images that make up such a small aspect of the overall site. Without alternatives, this might have been the only option to ensure the aesthetic of the site. However, it isn't, so good riddence.
sIFR
sIFR, or Scalable Inman Flash Replacement, is probably not a bad way to go if all I needed was to inject the font into the page. For lots of reasons it is a sane way to deal with fonts. However, I am working on a menu that needs rollover text effects and sIFR doesn't seem to have that functionality.
Pre-packaged Flash
There probably are existing menuing systems out there that will do what I need - honestly, I didn't even look. I had three requirements:
- Import links from an external XML document
- Embed custom font
- Handle rollover effects
Custom Flash
So writing my own seemed the sanest and to keep the size down, and because it is simple, there was no reason to use Flex. In fact, it was another opportunity to play with FlashDevelop, a free Actionscript IDE for windows. They have picked up the pace in releasing new builds and last week put out FlashDevelop 3.0.0RTM. As I didn't check for updates, I used 3.0.0RC5 in conjunction with Flex SDK 3.3.
I had worked earlier with Menus in Actionscript, but those focused on drop downs that had to integrate with helping javascript functions. I have one released into the wild, but in many ways it is a big pain. I am still going through refinement just in the placement of the menu on the page due to discrepency in browser layout engines, z-Index concerns and a host of other issues. Sufficed to say, I like the effect, but it can definitely be more trouble than it's worth (though there can be SEO benefits for the efforts, especially given that rel="nofollow" no longer removes links from bleeding pageRank). This menu is much simpler and my commented code is well under a 100 lines including Actionscript defined styleSheets.
Loading the XML
Loading an external XMl document is a straightforward thing and something that I do rather often. There are 3 steps:
- Creating a URLLoader
- Requesting the document
- Handling the Response
import flash.net.URLLoader;
import flash.net.URLRequest;
private function init(e:Event = null):void {
// STEP 1
var loader:URLLoader = new URLLoader();
// STEP 2
loader.load(new URLRequest("menu.xml"));
// STEP 3
loader.addEventListener(Event.COMPLETE, loadXML);
}
private function loadXML(e:Event):void {
// VOILA, YOUR XML
var _menuXML:XML = new XML(e.target.data);
}
If you use, FlashDevelop it can create an application skeleton for you. The above uses the nomenclature from that skeleton, so just place your URLLoader code in the init after the comment "// entry point"
Embedded the Font
Embedding the font is also not too difficult. You use a compiler directive to inject the font, and then you just need to make sure that embedFonts is set to true on TextField that will use it. In your StyleSheet or TextFormat object, you can then refer to the name of injected font and all will be well.
Here are the docs that cover the CSS properties available to Actionscript.package {
import flash.text.StyleSheet;
import flash.text.TextField;
public class Main extends Sprite {
[Embed(source = "ForgottenWorld.ttf", fontFamily = "ForgottenWorld")]
public var fntForgottenWorld:String;
public function Main():void {
// constructor fun goes here
}
private function addTextField() {
var txtField:TextField = new TextField;
txtField.embedFonts = true;
// I had originally used TextFormat, but styles
// really simplified my code
var style:StyleSheet = new StyleSheet;
// using an Object to define the various Style properties
var myStyle:Object = new Object;
myStyle.fontFamily = "MyEmbeddedFontName";
myStyle.fontSize = 14;
style.setStyle("a:link",myStyle);
txtField.styleSheet = style;
txtField.htmlText = "<a href='http://blog.shortfusion.com'>Furious Coding</a>";
addChild(txtField);
}
}
}
Rollover Effects
Getting the RollOVer effect is just a continuation of the above. All one needs to do is to define the additional style object that expresses the change in CSS properties and then connect it to the anchor state
I used the troyworks discussion of TextField actionscript hyperlink in AS3 to get my mind set straight on this. Before reading this article I was trying to do everything with the TextFormat object and was pretty much hitting a brick wall.private function addTextField() {
var txtField:TextField = new TextField;
txtField.embedFonts = true;
var style:StyleSheet = new StyleSheet;
var myStyle:Object = new Object;
myStyle.fontFamily = "MyEmbeddedFontName";
myStyle.fontSize = 14;
myStyle.color = "#0000FF";
// ADDING AN ADDITIONAL STYLE DEFINITION
var myStyle:Object = new Object;
myStyle.fontFamily = "MyEmbeddedFontName";
myStyle.fontSize = 14;
myStyle.color = "#FF0000";
// ADDED AN ADDITIONAL setStyle STATEMENT
style.setStyle("a:link",myStyle);
style.setStyle("a:hover",myStyle);
txtField.styleSheet = style;
txtField.htmlText = "<a href='http://blog.shortfusion.com'>Furious Coding</a>";
addChild(txtField);
}
When the site on which I am working goes live, I will post a link. Until then, I have run out of time to post an example - if someone really needs one, I can probably score some time to kick one out, but absent that, too many other demands on my time.


http://typeface.neocracy.org/
Unfortunately, for the usage I mentioned in this post, I would still choose to create a custom Flash strictly based on download weight. The js library it created for my typeface is about 45KB and when one couples that to the 20KB for the typeface-0.12.js that puts the whole solution at just over 60KB or about 3 times the size of my Flash movie + swfobject.js.
It is still very cool, and I imagine that there are optimization possibilities and perhaps differences due to the size of the font used (I am using one around ~20KB).
Thanks again
That said, using Flash with swfobject, I also have a regular, plain text menu in the div into which the Flash movie will be inserted - when it goes live, the plain text will be driven (via Coldfusion) by the same XML that drives the Flash. So I am assuming, perhaps wrongfully so, that the menu items will be completely accessible. Given that I finally did a release build last night and got it down to 9KB (based on a 20K font and incorporating text effects - had to use TextFormat over StyleSheets, but that's another blog) I don't know if there is going to be a superior solution for a simple menuing scenario - I'd love to be wrong though.