IFR: An FIR Alternative

Update

A revised, easier to implement version of IFR is now available.

I’ve dangled the carrot long enough. Here is the long awaited explanation of the Inman Flash Replacement technique (previously called Flash Image Replacement or The Other FIR). If you’re squeamish about 3 letter acronyms or my little blue code blocks you might want to sit this one out.

Why Inman Flash Replacement?

Other popular image replacement techniques are great for logos, top-level navigation and headlines on smallish company and personal sites but have far too much production overhead for larger sites with 100+ pages and primarily dynamic content.

By using a dynamic Flash movie (much like ESPN.com), some slick JavaScript and well-structured mark-up the same consistent branding can be achieved while greatly reducing production time and preserving the cleanliness of the mark-up.

Design Considerations

On this site and in this example I decided to copy-fit the text replaced by this technique for the sake of simplicity. A solid background was chosen to avoid any frustrations with Flash’s tendancy to pixel shift.

Structuring the Document

In this example I will focus on replacing <h1> tags in the the primary content of a page:

<div id="primary-content">
    <h1>Headline Being Replaced</h1>
    <h2>This could easily be replaced using the same technique</h2>
    <p>Lorem ipsum dolor...</p>
    <p>Sit amet morbi at urna...</p>
    <h2>We can even switch out multiple headlines</h2>
    <p>Magna dui pharetra...</p>
</div>

The unique id (or a class if your design is more modular) will be used later to target which group of <h1> tags to replace leaving all others untouched.

Set a Default Style with CSS

To accomodate those without version 6 or higher of the Flash plug-in or those with JavaScript disabled the document should be styled with CSS to approximate the finished look.

Create the Flash movie

Open up Flash MX and create a new movie name txt.fla (or download the .fla used to produce the .swf in this example). The stage can be any size since the <object> tag will be resized (without changing the scale) using JavaScript. Only one frame with two layers is needed.

Add the following actions to the first layer:

Stage.align="TL";
Stage.scaleMode="noscale";
Stage.showMenu=false;
_root.txt = txt.toUpperCase();

This tells the Flash plugin that the movie should be anchored to the top left of the area defined for it, that it should not scale (remember the width and height of the .swf will be controlled with JavaScript), and to disable the default Flash menu. The final line sets the Dynamic Text field (which will be created in the next step) to whatever is passed to the movie in the txt variable. Here I use toUpperCase() to convert the variable to all uppercase characters.

On the second layer, using the Text Tool create a Dynamic Text field on the stage. Select a typeface and size, color and alignment. Assign the field a variable name of “txt”. Enable “Selectable” and “Render as HTML” if desired. Click the “Characters…” button and select “Embed Font Outlines For: All Characters.”

To use two typefaces or colors in the same text field the string needs to be passed as two distinct variables that are then wrapped in <font> tags. (Don’t worry, these tags are added dynamically inside the .swf so we’re not mixing content and presentation.) You will also need to export the second typeface using the library palette. There is a contextual menu in the top right corner of the palette. Select “New Font…” In the resulting dialog box select the typeface you would like to export and then give it a name. This name is how you will refer to it in the <font> tag. Then right click on your new font in the library palette and select “Linkage…” Check “Export for ActionScript.” The short name you create earlier should be adopted for the Identifier and “Export in first frame” should also be checked. (See txt2.fla)

Now export the movie.

JavaScript Sleight of Hand

A minimum required version of the Flash plug-in must be detected first. For that I’ve created a distillation of the Moock FPI and Kirupa’s MX detection. Version 6 of the plug-in is required to utilize the FlashVars parameter. Variables could be passed in a query string to accomodate older versions of the plug-in but that forces the browser to hit the server for every instance of our movie. In theory, using FlashVars should allow the browser to cache the .swf.

Once the minimum version has been detected and the browser has proven itself capable of running the following code create an array all of the <h1> tags using document.getElementsByTagName('h1'). Then loop through the array. An <h1>’s parent node’s id or class can be used to determine if this <h1> should be replaced or left untouched.

The contents of each <h1> is stored in a variable and the <h1> is swapped out with an empty <div> which is assigned a class name. This can be used later to adjust the margins around the Flash movie or to provide additional graphical flourishes.

Next set the movie’s dimensions and prepare the FlashVars. Then create a new <object> tag as a string and insert it into our document with the innerHTML property (rather than the W3C preferred createElement() to prevent IE 5 Mac from getting crash happy). The loop will continue until all <h1> tags have been replaced.

Lastly set the script to run onload.

Additional Ideas

Here’s some additional ideas I’ve had for the technique but lacked the time to experiment with:

  • Dynamic, selectable text rotated 90 degrees.
  • Use with <blockquote> or <cite> tag to create dynamic pull-quotes.
  • Create two overlapping, different colored, slightly-offset Dynamic Text fields in your Flash movie but pass them the same variable to create a drop shadow or other effects.
  • Animate your headings.
  • Accommodate multiple lines of text. You would need to determine how many characters could fit in the width allotted. Then for each txt variable check each character backwards from the number you determine till you come across a space character. Replace that space with a <br>. Keep track of the number of <br>s added and set the height of the <object> tag accordingly.
  • Add a paragraph tag with the contents of the removed <h1> to the containing <div> we create. It could be hidden via CSS for screen mediums but toggled on in place of the <object> tag for printing to avoid rasterized text.

Shortcomings

With any new technique that mixes multiple technologies in an ever changing environment there’s going to be some limitations:

  • Those who have JavaScript turned on but the required version of the Flash plug-in turned off will see neither the original <h1> or the styled-text of the replaced movie. (Potential workaround: There is no way to determine if the plug-in is disabled despite being present. One approach would be to set the background of the containing <div> to an image alerting that there is content missing and provide a cookie-based toggle for this replacement function.)

  • Only a few HTML entities are supported in Flash. &copy; and &amp; are while &trade; is not. Luck may vary depending on the typeface chosen. (Potential workaround: Use JavaScript regular expressions to strip unrecognized entities.)

  • Copy-fitting required to use as is. (Potential workaround: See additional ideas above.)

  • Background graphics may be distorted by Flash’s notorious pixel shift. (Potential workaround: Use a solid background and be sure to set all type at least 1px away from the bounds of your Flash movie. Some have said that padding your graphic with an excessive border of transparent pixels can help eliminate this problem.)

  • Mozilla-based browsers appear to retain the margin-bottom of the original replaced element and then apply the newer element’s margin-bottom. (Potential workaround: Changing the height of the body and then resetting it to auto using JavaScript seems to force a redraw in Mozilla.)

  • Flash content displays above all other content regardless of z-index. (Potential workaround: It has been said that setting the wmode attribute to transparent can correct this issue—see Macromedia’s documentation for usage—but I haven’t much success with it.)

Previous
I Wanna Devise A Virus
Next
IFR: Revisited and Revised
Author
Shaun Inman
Posted
April 19th, 2004 at 7:35 am
Categories
CSS
Design
Flash
Inman Flash Replacement
JavaScript
Web
Comments
046 (Now closed)

046 Comments

001

wait, is this how you get fonts that are not installed on people’s computer to show up as selectable text? I have sooo been wondering how you did it, and now I know. So that must mean you are a GASP! communist.

Author
Danny Cohen
Posted
Apr 19th, 2004 4:01 am
002

No, he’s not a commie, he’s a witch.

Well done, Shaun.

Author
Papa Krantz
Posted
Apr 19th, 2004 6:25 am
003

At last! Sir, your a gent for sharing this technique.

I guess we’ll be seeing a lot more of this in CSS Sites from now. Certainly in my site…

Author
Jon Hicks
Posted
Apr 19th, 2004 6:31 am
004

You certainly are an artisan. Really really great idea Shaun… when you die, I will eat your brain.

Author
Jason Santa Maria
Posted
Apr 19th, 2004 6:46 am
005

Nicely done, degrades perfectly and can be added to the list of image replacement techniques.

Author
blakems
Posted
Apr 19th, 2004 6:46 am
006

Jason, sometimes you scare me. Can’t wait to see what you guys do with this…

Author
Shaun Inman
Posted
Apr 19th, 2004 6:54 am
007

As I’ve mentioned before… it took me FOREVER to figure out how he did that. It finially occured to me to look in the JS file, and lo and behold…!

Genius. Jason’s going to have some competition for that brain.

Author
John Whittet
Posted
Apr 19th, 2004 7:49 am
008

I haven’t looked at the source but it looks like this implementation has problems in your site on mozilla. The popup box for the search options on top gets messed up when over the “IFR: …” title of the article. Is it only me?

Author
Adrian Madrid
Posted
Apr 19th, 2004 8:07 am
009

That is actually a problem with the Flash plug-in. Many browsers (I believe all of them with the exception of the Mozilla family on OS X) display Flash content above all other content regardless of z-index. I forgot to add this to the list of known shortcomings.

Author
Shaun Inman
Posted
Apr 19th, 2004 8:11 am
010

I’m sure this will become a very hot topic in the next weeks as people unravel the mysterious beauty of the effect.

Have you ever come up with a solution to the Flash display delay — a FOUC of sorts — that occurs prior to when the Flash/JS to kick in?

Author
andrew
Posted
Apr 19th, 2004 8:41 am
011

Extremely well done Shaun. I have been looking into your method on ESPN.com for a couple of months now since I first saw it on your site. The only thing I can’t get past though is the rendering delay which displays browser text first and then Flash text a second later. Besides that, it’s perfect.

One workaround I’ve been experimenting with is dynamically writing out an < h1 > property in an inline css block which sets visibility to hidden as soon as the required Flash version is detected. This happens in the head element (and thus before the body has loaded) so there is no flash of unflashed content.

Again, well done Shaun!

Author
Mike D.
Posted
Apr 19th, 2004 9:40 am
012

Oops, just to avoid any confusion, I’m not responsible for the similar technique used on ESPN.com. Their use of dynamic Flash headlines predates my own. My technique just introduces removing the <object> and <script> tags from the inline mark-up.

It would appear that this separation of content and design through scripting is causing the flicker. I never really considered it an issue though (since portions of web pages have always loaded erratically) and as a result haven’t looked into any workarounds for it. Definitely open to suggestions/modifications as long as it doesn’t involve modifying the mark-up which would go against the primary objective of the technique.

Author
Shaun Inman
Posted
Apr 19th, 2004 9:58 am
013

Uhhhh, sorry to be the source of that confusion. I am missing a word in my previous comment. Should say, “I have been looking into implementing your method on ESPN.com…”. As in, I did the version on ESPN.com, but I like yours better from a markup standpoint.

Author
Mike D.
Posted
Apr 19th, 2004 10:35 am
014

This is too funny. Here I am explaining to you—Mike Davidson, whose work is the inspiration for this technique—that I’m not responsible for your work! Is my face red or what?

Author
Shaun Inman
Posted
Apr 19th, 2004 10:55 am
015

No sweat Shaun. Glad to have inspired this excellent technique of yours. It’s clearly the best way to achieve the rich typography we deserve to use and see on the web.

We launched our method on ESPN.com back in the Flash 4 days, and before good semantics were in fashion, so it’s really starting to look dated when compared to your method. Especially with dynamic stage sizing and flashVars available for use now in Flash 6/7, I think your replacement method is second to none.

Author
Mike D.
Posted
Apr 19th, 2004 12:42 pm
016

Oh, this is so good. You let the secret loose; expect to see this on all our sites, now ;) Impressive, impressive. Very good, Shaun.

Author
Christoph
Posted
Apr 19th, 2004 1:39 pm
017

OT: I’m not sure if this is just for my browser (Win IE 6), but whenever I try going to this site, Shaun, the site remains unstyled (no CSS is displayed) if I type in http://shauninman.com (w/o a trailing slash). However, when I type in the address w/ a trailing slash, everything’s styled and it displays properly. I’ve cleared my cache, and this issue still remains. Any ideas why?

Author
Christoph
Posted
Apr 19th, 2004 1:42 pm
018

As far as I can tell that’s an IE-only problem (as other browsers automatically redirect to the address with a trailing slash) but I have a feeling it might have something to do with my server config. I’ve known about it for a couple of days now but keep forgetting to ask my host about it. Thanks for the kick in the pants!

Author
Shaun Inman
Posted
Apr 19th, 2004 1:47 pm
019

Yahooooo! At last, the master speaks! I love you, Shaun, I really do. I thought I’d have to wait forever to finally learn… Thank you!

Author
Hans
Posted
Apr 19th, 2004 2:32 pm
020

Hmm, apparently hicksdesign.co.uk has a similar problem in IE, Christoph. Looks like the stylesheets load but the images do not. I’m trying to get to the bottom of this…

Thanks for the kind (and sometimes scary) words, guys.

Author
Shaun Inman
Posted
Apr 19th, 2004 3:49 pm
021

Oh, You’re good :)

Author
Jake Nickell
Posted
Apr 19th, 2004 6:33 pm
022

“No, he’s not a commie, he’s a witch.”

Honestly. The real question here is “Does he weigh as much as a duck?”

Author
Forrest
Posted
Apr 19th, 2004 6:48 pm
023

I’ve wondered how you did this ever since I first came to your site. I’ve always wanted nice looking din headings. Thanks for the explenation.

Author
Bradlay Law
Posted
Apr 20th, 2004 12:35 am
024

I thought you could embed fonts with Windows Embed Font Program.. Its free too

Author
PatrickAlgrim
Posted
Apr 20th, 2004 4:42 am
025

It’s also proprietary Patrick. Unfortunately—or as I look at it, fortunately —not everyone is using IE on a Windows platform so it’s not a viable option in a production environment.

Author
Shaun Inman
Posted
Apr 20th, 2004 4:45 am
026

Shaun, the problems on my site was due to me fiddling with my .htaccess to stop hotlinkers. It kinda screwed things up, especially those in IE Win and that trailing slash problem.

One advantage of this FIR method which has only just occured to me, is that you don’t have t waste time creating lots of images! I like this more every time I think about it.

Author
Jon Hicks
Posted
Apr 20th, 2004 6:03 am
027

Jon, you don’t realize how hard you rock! Problem solved. I just changed this line in my .htaccess file:

RewriteCond %{HTTP_REFERER} !^http://(www.)?shauninman.com/.*$  [NC]

To:

RewriteCond %{HTTP_REFERER} !^http://(www.)?shauninman.com(/)?.*$   [NC]

Wrapping the trailing slash in ()? makes it optional. Everything loads correctly in my test environments now.

Author
Shaun Inman
Posted
Apr 20th, 2004 6:11 am
028

I may sound like a n00b, but I have a question on your code. in your normalizeWhitespace function you have the following

/s+/gi

what exactly is this doing? I’ve seen this in a couple of code examples I’ve been reading around the web and it sorta baffles me.

Author
Funkatron
Posted
Apr 20th, 2004 6:52 am
029

/s+/gi is a regular expression that finds an occurrence of whitespace (meaning a single space or tab represented by the s) followed by any number of additional whitespace characters (indicated by the +). The gi tells the RegExp parser to search globally (replace more than one) and to do a case-insensitive search (unnecessary in this instance but probably included out of habit). Unlike HTML, Flash doesn’t condense whitespace so the SI_normalizeWhitespace() function does it for us.

Author
Shaun Inman
Posted
Apr 20th, 2004 7:04 am
030

You wouldn’t happen to know any good links that explain RegExp?

Author
Funkatron
Posted
Apr 20th, 2004 7:08 am
032

Thanx very much

Author
Funkatron
Posted
Apr 20th, 2004 7:37 am
033

could someone make some more examples of this method? I don’t have Flash, so I don’t really know what is up, but a gallery with showing the regularly styled text and then the Flashy styled text would be nifty.

(Do you think one could do this in ImageReady with it’s support for exporting .swf’s?)

With all this talk of brain eating, I think we are forgetting his luscious pharynx, tender venter, and chewy bit-sized digits.

Author
Danny Cohen
Posted
Apr 20th, 2004 9:08 am
034

I’ve been waiting for you to publish the dirty details for a while, and can’t wait to use the technique.

I take it it’s open source, or free to implement on our own sites?

Author
kemie
Posted
Apr 20th, 2004 9:45 am
035

Of course! I just ask that you use your own type treatments and not just the swfs provided.

Author
Shaun Inman
Posted
Apr 20th, 2004 10:00 am
036

Comrade

*”So that must mean you are a GASP! communist.”… *said Danny Cohen.

Well Shaun, after the revolution, you will stand on a balcony and all other web developers will salute you as they march past.

Well done Comrade, great work!

Author
Malarkey
Posted
Apr 20th, 2004 10:08 am
037

Congrats on the trailing slash fix, guys. Interesting, though, how the .htaccess made all the difference.

Author
Christoph
Posted
Apr 20th, 2004 1:17 pm
038

I feel like I just stepped into a room full of geniuses! And perhaps I have. Excellent, excellent technique. Something to be proud of for sure. And the way you and Hicks worked together up there to solve a problem…it brought tears to my eyes:p Truly, the days of hiding our deepest and most secret techniques from each other are over.

Author
Peter Zignego
Posted
Apr 20th, 2004 4:20 pm
039

Wow that is really great man, thanks a lot man.

Author
Khalil Waldropt
Posted
Apr 21st, 2004 5:07 pm
040

I love this technique, thank you very much for sharing it!

Author
Bobby
Posted
Apr 23rd, 2004 12:29 am
041

One thing to watch out for is the presence of multiple flash files on one page can have strange effects when they overlap. For example, the search widget on this page is partially covered by the nearby Flash header of a blog entry. (Safari only maybe?) You might be able to solve that with z-index incrementing somehwere.

Author
andrew
Posted
Apr 23rd, 2004 5:05 am
042

Four issues I noticed with this technique:

  • When attempting to load this page with Firefox (Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040206 Firefox/0.8 to be exact), my processor pegged at 100%, the page failed to load, Firefox froze, and I had to force-quit. Firefox loads the front page of your site just fine.

  • With IE (6.0 SP1 on Windows XP), the page loads fine, but the IFR elements remain hidden for a few seconds after the rest of the page loads.

  • Again on IE, when it loads this page, the memory that IE uses goes from ~14K to ~43K. The memory usage on your front page is lower, around 27K.

  • Content “flashes” in both IE and Firefox. That is, when the javascript goes through and replaces all of the h1 tags with div tags, the titles flash and the content repositions itself on the page (I’m assuming this is because of a difference between the height of the h1 and the div tag that replaces it).

In short, on the two browsers above (will check tonight on all my Mac browsers), this page takes a long while to load and then settle down because of the extensive use of the IFR technique, especially since the page is mostly text and should take no time at all to load. When evaluating whether to use IFR, I’d be careful to balance the benefits of its use with the potential slowdown in the browsing experience for some.

Author
jkottke
Posted
Apr 23rd, 2004 12:48 pm
043

That appears to really only be two issues in two browsers: processor usage spikes and flash of partially styled content. I’ll be posting a fix to the FOPSC problem later tonight.

This site actually uses a much more involved, less refined version of IFR explained in the article that accesses nested and adjacent nodes to build the Flash movie. That and the sheer number of comments on this particular page could account for the processor usage spikes. Safari, IE Mac, and Mozilla browsers on OS X all seem perfectly capable of rendering the page.

I think both things you mentioned are relevant concerns that hopefully my revision will address.

Author
Shaun Inman
Posted
Apr 23rd, 2004 1:00 pm
044

werd… i’ve been thinking about this for ages. soccernet.com does it and i’m getting sick of making a flash headline by hand for my site each week. just today i really set to considering it and BAM by chance i stumble across this. many thanks.

Author
mmmart
Posted
Apr 23rd, 2004 9:33 pm
045

WOW !! I never been a big fan of Flash except for the possibility to use any font that I want” Now I’m pretty sure I’ll use your technique on my next site.

Thanks.

Author
stephane
Posted
Apr 24th, 2004 4:48 am
046

A revised, easier to implement version of IFR is now available.

Author
Shaun Inman
Posted
Apr 24th, 2004 5:10 am