Proper Flash embedding: FlashObject Best Practices

UPDATE (7-24-2005): This page refers to an old version of the FlashObject script. For questions or comments, or to download the script, please refer to the permanent home of the FlashObject script.

This post is a continuation of a previous post. Read this for more background information on the FlashObject embed method.

In the months since I posted the FlashObject embed I’ve had a chance to talk to a number of developers and use it in a few high traffic projects. In doing so I’ve picked up some tips and best practices that I’ll be outlining here. I’ve also revamped the FlashObject script so it’s a bit more light weight and fixed a few small bugs.

What’s new?

  1. Alternate content is no longer written to the page by default – You may still use the fo.altText variable to add alternate content to your pages, but it is not recommended. The way to display alternate content in your pages with Flash content would be to place the alternate content on your page, and then specify the ID of the element with your content inside. The FlashObject script then writes your Flash content inside that element, replacing your alternate text/content so the end user with Flash will never see it, but users with no Javascript or without the required Flash version will see the alternate content. Google will also index your alternate content since it is just plain HTML.

    Here is an example of what your embed should look like:

    <div id="flashcontent">
      Place your alternate content here and users without the Flash plugin 
      or with Javascript turned off will see this. 
      Include a link to <a href="?detectflash=false">bypass the detection</a> 
      if you wish.
    <script type="text/javascript">
     // <![CDATA[
      var fo = new FlashObject("fo_tester.swf", "fo_tester", "300", "150", 6, "#336699");
     // ]]>

    Because of this change, you should always specify the ID of an element to write your Flash content into. You should also be sure to always include alternate content on the page. If your Flash movie is purely decorational, you can leave the div empty, similar to using empty alt attributes (alt="") on decorational images. Also note that with the new version you need to place your Javascript that writes the Flash content after the element that will contain your Flash content, as in the example above.

  2. Support for pulling variables from the URL string when using anchors – There have been some discussion about Flash state tracking and direct or ‘deep linking.’ Most of the methods rely on parsing variables from the URL when the movie loads, so now you can pull vars out using the built in function getQueryParamValue().


    If your URL is:


    You can pass those vars into your Flash movie by using the following code:

    var fo = new FlashObject("fo_tester.swf", "fo_tester", "300", "150", 6, "#336699");
    fo.addVariable("var1", getQueryParamValue("var1"));
    fo.addVariable("var2", getQueryParamValue("var2"));

    The same works for normal URL parameters in URLs such as:


Just to recap some of the things posted in the previous FlashObject post, here’s some of the thinking behind the FlashObject embed method:

Why Javascript?

Javascript is the best overall solution for a number of reasons, among them:

  1. With Javascript you can detect the presence of the Flash Player on your user’s system and either display the Flash content or leave the existing (X)HTML on the page. This is also a huge advantage when it comes to search engine indexing since the alternate content is on the page and will be indexed as normal content. This also prevents novice users from seeing Internet Explorer’s ActiveX install box, which on Windows systems pre-SP2 is a very scary thing these days with all the Spyware and Malware running around on the internet. On most other browsers, you’ll likely see some empty box where the Flash content should be, sometimes with a broken image or puzzle piece icon which most novice users have no idea what to do with (Should they click on it? Is it part of the site?). If you include well written upgrade/install instructions in your alternate content, all of these problems are avoided.
  2. No Extra configuration files for each Flash movie. Some alternate methods of embedding Flash content in XHTML documents include using extra configuration files or ‘holder’ movies that load in other movies. With this method there is no need for any extra files aside from the single .js file.
  3. Easy to serve different content to different browsers. I worked on a project recently that made extensive use of the wmode=transparent option. Well when you are using IE or Firefox you can use wmode=transparent with the Flash 6 player, but if you are using Apple’s Safari browser, you need Flash player 7 to see the content properly. So in the embeds on the page, we required Safari users to have the Flash 7 player, and everyone else the Flash 6 player. Without Javascript we would have had to force everyone to upgrade to Flash player 7, something we didn’t want to do, even though the Flash 7 player has a pretty high penetration percentage.

Problems with Flash Satay/pure Object tag embedding

The main issue with using any embed method that uses only object tags to embed any plugin on a page is that Safari ignores the param tags. For very basic embeds this isn’t a problem, but when you want to start passing in variables or change the background color of the movie without re-publishing it you start to run into problems.

The one area where using pure object tag embeds shine is in using XHTML pages that are sent with a mime type of application/xhtml+xml. Since the FlashObject script uses innerHTML and sometimes document.write, it is not compatible with pages sent with the application/xhtml+xml mime type. Currently I have no plans to update it to work with these pages, as there are many issues with creating object tags using the DOM because almost every browser engine handles it differently and has little quirks that make it very hard to work around. If you are interested in seeing some of the code it would take to embed Flash in XHTML documents, check out the excellent Javascript that comes along with sIFR 2.0.


Download the source to FlashObject 1.1.1.

Download the source to FlashObject 1.3.

View sample pages using FlashObject 1.2 in different Flash embed situations.

UPDATE (5-5-2005): If anyone is interested, Paul Newman has wrapped this script into a Dreamweaver extension. It costs $15 (or free to CommunityMX subscribers), but if you are a not-so-technical Dreamweaver user I think it would be worth it.

UPDATE (5-17-2005): Made a small change to the embed tag output. I changed the id attribute to a name attribute as Firefox needs it that way in order to use LiveConnect and talk to the plugin via Javascript.

92 thoughts on “Proper Flash embedding: FlashObject Best Practices

  1. Keith,

    You could modify the fo.write() method to change the content of your div to show the version number if you wanted to, but it would take a bit of work. I have just been hard coding it on the page, as I almost always make custom alternate content for each Flash movie.

    the doDetect var is checking for the string ‘false’ because it is pulled from the query string of the url as a string, but if you wanted to remove the quotes you could, as Javascript should evaluate the string ‘false’ as the boolean false.

  2. Yes, since am putting the version into the script, no big deal to put it into the alternate.

    Just ran into something else.
    Had a question as why my swf seemed to put itself at a higher z level than surrounding content.
    From, it seems that there is a wmode parameter than can affect this.
    I tried using
    fo.addVariable(“wmode”, “opaque”);
    like I added other parameters. That didn’t cause the right adjustment.
    If I put it in as a regular parameter with the embed object, it does the correct effect.
    Seems like the fo.addVariable(“wmode”, “opaque”); should work with FlashObject as it works with other parameters I used.

  3. Hi, here’s a little contribution:
    The document.getElementById method is not recognised in every browser, here is a code to add in the begining of your script to make it work in IE4 and NS4:

    if(document.all && !document.getElementById) { /*ie4*/
      document.getElementById= function(id) {
      document.getElementsByTagName= function(id) {
    if(document.layers) { /*ns4*/
      document.getElementById= function(id) {
  4. Thanks! I won’t be adding that code into the main build, as I haven’t had to support ns4 for almost 2 years now, but it’s good to have the comment there for other people if they need to add that functionality.

  5. For the function “getVariablePairs”, I found that the escape function was causing problems with such things as right single quotes. I removed that, and it now runs fine. Is there a specific reason you put that here (and not in the getParamTags function)?

    FOP.getVariablePairs = function() {
          var variablePairs = new Array();
          for (var name in this.getVariables()) { 
            	variablePairs.push(name + "=" + escape(this.getVariable(name))); 
          return (variablePairs.length > 0) ? variablePairs.join("&"):false;
  6. Yeah that was an issue that popped up early on, and I removed it, but then decided to put it back in later. The problem is with unicode characters – escape() doesn’t handle them so well, so if you have to use them you can try using encodeURIComponent() instead, but the problem there is it doesn’t work in IE5 or Netscape lower than 6.

    As for best practices, I would recommend loading in content using an external XML file or text file instead of passing the info directly into your Flash movie.

    And the reason it’s not in the getParamTags() function is that there are no parameters with characters that would require escaping.

  7. I am currently developing a site using a modified version of FO, wherein I use the onload javascript event from within an external script mentioned in the document head. This eliminated the need to have extra script tags after each replaceable element in the markup, keeping things nice and clean. During script load, meaning before the onload event, I set the visibility of the replaceable to hidden and have the onload event reset the style to visible to avoid FOUC, too. All of this works really nicely in every browser I have access to, including: IE5+/Win, Opera 6+/Win|X11, FF1+/Win|X11, NS7/Win, KHTML3.2+/X11.

    Now, my only thing is wanting to eliminate the EMBED tag, since I want HTML 4.01 Strict to actually mean what it claims, even in Netscape-alikes. I realize this is a pain due to Safari ignoring PARAMS within OBJECT, but I have an idea:

    From what I understand, there is a method of passing variables to Flash via data sources like POST and GET using Actionscript’s LoadVars() method. Would it not be possible to simply manipulate one of the data sources LoadVars() can access, thereafter using said data source to pass into Flash such values as you would normally pass via a PARAM?

    Just for the sake of fleshing out the idea a bit, given that we are already scripting, this data source manipulation step could be taken after we have determined Flash to be available, but before the markup is actually written to the document. Then, anything that the Flash movie must set up ‘on load’ will be available for the movie to do some dynamic configuration, such as set the background color before rendering Frame 1.

    Anyway, it’s just a thought. I am not generally a developer who uses Flash, but I had to do it for my current project. I would be interested to see if this idea could be fleshed out and possibly help overcome the inherent problems of applying the Hicks-style OBJECT-only techniques and at the same time make the actual rendered markup as compliant as the original source (e.g., no EMBED tags).

    Anyway, cheers.

  8. Hey Ray,

    Some comments on your post:

    1) While using the onload event is tempting (and I’ll admit, much more ‘clean’), I don’t use it because if a user has Javascript disabled, in a browser that supports CSS, they will see no content at all, which is bad.

    2) The newest Safari update seems to support param tags now – I haven’t done a full set of tests, but Safari 2 and 1.3 on OSX 10.3 seem to be working correctly now, so that takes care of the main problem I had with using ‘Object tag only’ embeds, but since there will still be users out there who don’t upgrade to the latest version, it will be a while before I make any changes to the FlashObject script.

    Your idea of passing in the params using an external data source will work, and there is already a Flash embed method that uses that type of method. It uses an external XML file with the parameters like Stage.align and the background colors (I think). I’m not a fan of this mainly because you have to keep an extra XML file (or pass the vars with a query string) with each one of your Flash movies which seems like a lot of extra hassle. (Flash Totanus Loader)

  9. Geoff,

    Thanks for the reply.

    I can concede to your logic for using deprecated markup for compatibility sake. I also see the hassle posed by Flash Totanus Loader’s approach. However, I think you did not fully comprehend what I meant about my use of the onload event solving FOUC. With CSS enabled and JS disabled, nothing ever changes in the page and the content is not hidden in any way.

    I do this:

    In the head, I link to an external script:

    <script type="text/javascript" src="script/dynamic-elements.js"></script>

    That external script includes your FO code and a little extra. When that external script is initially read, the browser comes upon this:

    hideDynamic = '<style type="text/css">';
    hideDynamic += '<!-- #home-intro, #browse {visibility: hidden;} --></style>';

    hides my flash container / fallback content element in the markup (obviously this is for one element with id=”home-intro”, but it could easily apply the style to a class instead). It programatically inserts the style into the document head, so CSS on, JS off is not a problem. Fallback content already exists in that element and is left visible in the static stylesheet. :)

    After the document completely loads, the onload event kicks in, as expected.

    At this point the scripting engine runs an ‘init’ function which sets the configurations you would normally place in the markup document after the element to replace. After that, it calls the FO functions to create the FO object and replace the designated content if Flash is installed. In any event, the element visibility is switched back on before the script ends by calling the showDynamic() function right before ending script execution.

    This approach kills any FOUC and all of the associated reflow acrobatics that may happen as a browser tries to layout the page for the initial fallback content and then compensate for a Flash movie of different dimensions than the fallback content. This increases usability, in that content and forms which have already loaded into the page are readable and can be used while the page is still loading, instead of (from a visitor perspective) arbitrarily jumping around (due to reflow). :)

    Here is the relevant code to show what I mean:

    hideDynamic = '<style type="text/css">';
    hideDynamic += '<!-- #home-intro, #browse {visibility: hidden;} --></style>';
    function showDynamic() {
      document.getElementById('home-intro').style.visibility = 'visible';
      document.getElementById('browse').style.visibility = 'visible';
    // ...
    function init(){
      var fo = new FlashObject("intro.swf", "flash-home", "546", "314", 6);
      fo.addParam("menu", "false");

    found this to both be a fully accessible approach, and much cleaner than embedding scripts into the markup.

    Anyway, I thought it might be useful to someone, even if you don’t decide to involve it with FO proper.


  10. Pingback: JD on MX

  11. I had a nasty surprise – Safari: if the user has flash installed, but has chosen to disable plug-ins then the user doesn’t see anything – the alternative content is not displayed. The detect script is not broken, it is reporting that, yes, flash is installed, but it doesn’t detect whether it’s enabled.

  12. That problem popped up a while back, and as far as I can tell, there is no way to determine if the user has Flash installed but has it disabled. In my opinion, this is a bug in Safari. The browser should alter the navigator.plugins array when you disable a plugin.

  13. Starting from the W3C validator, i spent the night reading on embedding flash files, from Satay to everything existing around. Now Geoff’s FlashObject will be inserted in all my projects. Congratulations and sincere thanks.
    Hmm… what could be in the “but” ? Maybe 6ko and a .js file more, but what do you want for nothing, this is the price for a good flash detector, isn’t it ?
    Satay is also very tempting, naked, straight and fast. I think i will use it sometimes, in complement of FlashObject.

    Some comments on the files you provide in your :
    - the “?dodetect=false” is still present instead of the “?detectflash=false” in the html files.
    - why not include a simple addParam line (like quality or wmode) just as an example in the main flashobject.html file ? (I’ve been stucked for a while with ‘fo.addVariable(“wmode”, “transparent”);’. Yes, the bed was walking to me at this moment…).

    And finally, why not create an official URL for flashobject.js that everyone can link to, without copying the file for every project, always relying on latest updated file, probably making you more famous than you are and all kind of things everyone can imagine that let you earn all the money that you diserves, sport cars, champaign and women.

    FlashObject successfully operating on latest versions of Opera, IE and Firefox under WinXP. Not a scoop…

  14. Hey, thanks for the script it has been very useful. One thing I don’t understand is this: if my alternate content contains lots of images (e.g. a nav with rollover images).. do these get loaded even if the user has flash installed? or does the flash user only have to load the flash? Apologies if there is an obvious answer.. i’m not very techy

  15. Well, I think of you place the js function to replace the alternate content just below it, then the browser won’t have a chance to load the alternate content, and the images won’t get loaded… But I haven’t tested this extensively, and different browsers might behave differently. If anyone wants to run some tests, I would be very interested in the results.

  16. grossebaf,

    Thanks, I’ll see if I can get all that stuff cleared up.

    As for a single URL for the flashobject.js file – I would rather not do that… There are potentially thousands of people using the script, so the strain on my server would be something to consider, and if for some reason my server was down, all their Flash content would stop working.

    I would suggest checking back to this post every once in a while to check for updates, or subscribe to my RSS feed to see when/if I release updates to it.

  17. Hello!

    I may well be being a little stupid here but i’m having a problem trying to put more than one flash object in the page at the same time. i need this page to validate XHTML 1.0 Transitional and it’s not happy about using the same ID tag more than once (id=”flashcontent”). i’ve tried taking one of them out and changing it’s name but it drops one of the flash objects when displayed in the browser.

    If i’m missing something obvious then sorry but i really need the help.

  18. Great script although I am experiencing an unusual problem…

    I have used the script within a php page to automatically fill in the navigation. Each element within the navigation is a small swf file where name and url parameters are passed. Using IE, before the swf objects are cached, many of the flash files don’t load properly until it gets some way down the navigation elements. Pushing ‘refresh’ fixes the problem and the problem doesn’t seem to exist with Firefox at all. To reproduce the problem I clear out the temp files then reload the page.

    I have placed a sample of the problem at

    Does anyone have any idea what is causing this and how to fix it? It’s been driving me crazy for days trying to figure it out.

  19. First, well done. I like your work.

    However, for Internet Explorer 6 on XP, I’m getting a Flash of the content that is to be replaced a second before the Flash object is embedded. Is this a known issue?


  20. I finally found an ‘almost’ workable solution to my problem mentioned above and it may help anyone else who needs to load in multiple instances of their movie files.

    First of all I should outline what the problem appeared to be (please correct me if I have not explained the process):-

    In IE6 and FlashPlayer 7, each Flash movie is loaded directly into memory as it loads in the page. If the movies are all different there is no problem because the FlashPlayer merely loads each according to its specification. If, however, the movie is duplicated then the FlashPlayer appears to start loading the movie while the rest of the page loads. When it receives the next command to load the same movie with different parameters, it uses the progress of the first movie as its starting point and, importantly, leaves the original movie in limbo. This continues through all the instances of the movie until the movie is finally loaded completely. Once it is loaded in one of the instances, all subsequent instances load properly but the original unloaded movies stay unloaded.

    You most likely wont see this occur on your local test machine because it will load the movie file quickly. Online the download speed is much slower and this is where the problem shows itself. Make sure you delete all instances of the movie from your temporary files cache before each test as the page will simply use the cached version and not show the problem.

    To correct this, the FlashPlayer needs a fully loaded instance of the movie before it will load the multiple instances correctly. To control this a dummy instance of the movie is placed in a hidden div block at the top of the page. Then the javascript window.onLoad call is used to activate all the movie instances after the page has finished loading.

    The only problem with this solution is that the divs containing the instances of the movie during the loading process need to be hidden, then made visible in the window.onLoad call. If the viewer doesn’t have javascript turned on in their browser then the non-flash alternative will also remain hidden.

  21. I figured out why for IE6/Win it was displaying my alternate content before replacing it and rendering the Flash. I’m importing my CSS file, and apparently this is a problem. Here’s an example.

    When I link the CSS file or write the CSS directly on the page, the FlashObject embed works perfectly in IE. But, unfortunately, I don’t want to do this, because I don’t want older browsers choking on my CSS. I’d rather they get nothing.

    Do you think this is just some strange IE bug? Is there any hope that the FlashObject method can be modified to correct this? Or is my only hope to detect the browser with JS and then link my CSS file if it’s a modern browser?

  22. Hmm, it sounds like it might be related to the FOUC bug in IE. The way that I work around that bug is to add all ‘normal’ css files using import, and then add in a print stylesheet using the link tag. This way you avoid the old browsers showing messed up css and IE won’t do the FOUC.

    BUT, I did look at the FOUC page, and it said that a single script element in the head will prevent it, and it looks like you are embedding the FlashObject script in the head? So I’m not sure. Maybe you found a completely new issue.

    Anyway, if you want to try this fix: import all your stylesheets as you normally would, then add one more stylesheet and link it as a ‘print’ stylesheet – check the link to the FOUC page for an example.

  23. I added a link to my print style sheet, and that fixed the problem. It’s one of the last things I add to the site, so I didn’t have it in there yet. Though I would not have thought that not having it was the solution for IE. So thanks.

    I didn’t consider the FOUC bug because of the script elements I have in the head. Typically, that works. But apparently not so for the FlashObject solution.

    Thanks for your help.

  24. In your changelog for v1, you mentioned that you took away the codebase attribute in October 04 because the flash tag wouldn’t get written in the first place if IE wasn’t already good to go. Consider putting codebase back in. There is at least one case where IE can have flash installed and pass flash detection, yet not display the content unless the codebase has been set. Not sure how it happened, but I have seen it happen.

  25. The codebase attribute is only used by the browser if you don’t have the plugin installed and the browser tries to find the files it needs for the plugin. It has nothing to do with actually displaying the Flash content if the user already has the plugin.

    Since the script doesn’t write the object tag to the page if there is no plugin detected, the browser would never use the codebase attribute to locate the missing plugin.

    If you have any examples of bugs or problems specifically with the FlashObject script, please post a link or e-mail me the files so I can test them out.

  26. Geoff: I haven’t gone through all of the new comments in this thread since the last time I looked at it a couple of months ago, but with regards to the “caching” problem noted above by Das, it sounds eerily similar to something we ran into with sIFR where in some installs of IE, the replacements would basically happen too quickly thus crapping out and sometimes hanging the browser. The way around this (and a small handful of other timing-related bugs in both IE and Safari) is to call your function from another function using a setTimeout of any value. Even zero works. I use “1″ because I just can’t get myself to write a setTimeout function and wait “zero milliseconds”… just feels wrong.

    Anyway, that fixed the problem when it cropped up in a sIFR beta release a few months ago, so it may also fix this.

  27. Thanks for your suggestions Mike.

    I had originally used setTimeout() and it appeared to work OK for small numbers of flash elements (about eight or so). When the number of elements increased it didn’t actually fix the problem ( see ).
    Also, it was difficult to control the timing of the non-flash components. The test page listed hides the flash divs and then makes them visible after the page loads. But the setTimer doesn’t activate until after the page has loaded and so the results can be ugly if the non-flash content is visually different from the flash content.
    Do you have any examples of how you used setTimer() to solve your problem?

    By the way, I should point out that this problem exists no matter how you place the flash content in the page – it isn’t a problem with Geoff’s script.

  28. thanks for the code, it was very helpful.
    but I have a question about an issue I couldn’t resolve.
    how can I do to pass new parameters to the swf movie when I resize the browser?
    I want to change the dimension of the swf when I resize the window.
    thank in advance.

  29. Can someone email me with the detractors of using this:

       <object data="index.swf" type="application/x-shockwave-flash" width="633" height="395" hspace="0" vspace="0">
                            <param name="movie" value="index.swf" />
                            <img src="../../images/getflash.gif" alt="flash" width="633" height="395" hspace="0" vspace="0" />
  30. I have been using ADxMenu with FlashObject and encountered the same layering problems that have already been mentioned. My work-around is slightly different in that I’ve added a couple of simple attributes to the JS code. Which tests fine in the latest versions of Firefox, IE, and Opera (Windows). The warning about Safari and Flash 6 is an acceptable margin of error for me in my situation.

    Added to the end of the flashHTML += ‘<embed ..’ line inside the FOP.getHTML function:


    Added to PC IE architecture inside the FOP.getHTML function:

    flashHTML += '<param name="wmode" value="transparent" />';

    Now my ADxMenu drop-downs float on top of the Flash movie using CSS z-index.

    Source Code Changes

  31. Pingback: Xander's Blog

  32. Jason,
    There are a few things I don’t like about using just an object tag like that – read this post and the previous one, as they both discuss the problems with each type of embed.

    David, you can set the wmode parameter without editing the js file…

    Just use: fo.addParam("wmode", "transparent");

    That way you can pick which movies are transparent and those which shouldn’t be.

  33. Pingback: Xander's Blog

  34. This appears to break in Netscape 7/8. I have it working in Firefox (which I thought was the same engine as N8…) and IE. In Netscape, I get the broken puzzle instead of the alternate content. I have a div with a paragrpah containing an image as my alternate content, and the script tags immediately below. The script looks like this:

    <script type="text/javascript">
    // <![CDATA[
    var fo = new FlashObject("/us/swf/75LogoAnim.swf?from=homepage", "fp_animation", "162", "188", 6, "#eee");
    fo.addVariable("flashVarText", "this is passed in via FlashVars");
    // ]]>

    Apologies if this is something simple I’ve overlooked…I’m really quite incompetent with Flash.

  35. Eric,

    That is very odd that it displays the puzzle piece. That means that the FlashObject script found the correct plugin in the browser’s plugin array and wrote the object/embed tag out but then the browser couldn’t find a plugin to load the swf.

    Are you sure you have the Flash player installed correctly on each browser you are using? Netscape 7 and 8 are very different browsers. Netscape 8 can switch between IE rendering mode and Gecko rendering mode, so be sure that if you installed a plugin, that plugin is installed for each browser.

    I just downloaded Netscape 7 and 8 on my test PC, and both of them work fine on my example page. Does my example page work for you?

  36. No, the sample page is broken as well. In fact, all your high profile projects do the same thing. What I’m actually getting, though, is a broken quicktime icon now (I can’t remember what I had a few days ago). This is with Flash NOT INSTALLED…so it should be going to the alternate content. I’m sorry to be confusing – I’m sure I was getting the puzzle piece when I wrote the first message, but now it’s just the broken page Q icon. When I install Flash, I get the Flash movie, it’s only when I don’t have Flash installed that it breaks.

  37. Hmm, I’m still convinced that it’s something specific to your install. Most likely the browser thinks the Flash player is still there even though you have removed it.

Comments are closed.