Lab: SWFObject

Toggling a SWF's visibility

Many people have asked how they can dynamically hide a SWF using JavaScript and CSS. There is only one method that works well for me in IE6, Firefox 2 and Safari 3.1 (Windows): setting width and height to 0.

One of the big changes between SWFObject 1.x and SWFObject 2.0 is that SWFObject 2.0 replaces the target DIV with the object element while SWFObject 1.x simply placed the object and/or embed elements inside the target DIV. Since we no longer need to deal with the container DIV, we can simply set the width and height of the object element to zero, and all content on the page will shift as if the SWF were never there.

Notes:

  • I'm using a class ("hidden") to handle the width and height; I find classes to be a cleaner, easier solution than applying the styles to the element via JavaScript.
  • The static publishing method requires using swfobject.registerObject and the SWFObject 2.0-specific swfobject.getObjectById method. This is necessary because of the nested objects (read more here). The dynamic publishing method uses the plain vanilla document.getElementById.

Working examples: static publishing | dynamic publishing (tested in Firefox 2, IE 6, and Safari 3.1 Windows).

Static publishing code:

<script type="text/javascript">

swfobject.registerObject("flashcontent", "7.0.0", "/lab/_common/expressinstall.swf");
	
function toggleSWF(){
   var swf = swfobject.getObjectById("flashcontent");
   if(swf.className == "hidden"){
      swf.className = "";
   } else {
      swf.className = "hidden";
   }	
}

</script>

<style type="text/css">
<!--
.hidden {
   width: 0;
   height: 0;
}
-->
</style>

Dynamic publishing code:

<script type="text/javascript">

swfobject.embedSWF("/lab/_common/sample.swf", "flashcontent", "550", "400", "7");
	
function toggleSWF(){
   var swf = document.getElementById("flashcontent");
   if(swf.className == "hidden"){
      swf.className = "";
   } else {
      swf.className = "hidden";
   }	
}

</script>

<style type="text/css">
<!--
.hidden {
   width: 0;
   height: 0;
}
-->
</style>

Other toggling methods and their drawbacks:

Using the negative text-indent CSS hack to hide the SWF.

This method hides the SWF, but the parent DIV remains visible. This might be useful if you have a background image applied to your DIV.

Working examples: static publishing | dynamic publishing (tested in Firefox 2 and IE 6).

function toggleSWF(){
   var swfDiv = document.getElementById("flashcontent");
   if(swfDiv.style.textIndent === "-9000px"){
      swfDiv.style.textIndent = "0px";
   } else {
      swfDiv.style.textIndent = "-9000px";
   }
}

Modified text-indent hack

The text-indent trick can be modified to set the container DIV's size to width: 0 and height: 0, similar to the visibility: hidden trick. This works fine in Firefox 2 (WinXP), but the DIV doesn't resize properly in IE6. In IE6, the box model forces the DIV's height to be as tall as the content it contains. Even though we've hidden the content with the negative text-indent hack, the content is still technically in the DIV, so it stays enlarged.

Also note that when resizing the DIV in this manner, other CSS styling gets lost: the DIV's background color and border are somehow turned off in both Firefox and IE6 (but only in SWFObject dynamic publishing mode).

Working examples: static publishing | dynamic publishing (tested in Firefox 2 and IE 6).

function toggleSWF(){
   var swfDiv = document.getElementById("flashcontent");
   if(swfDiv.style.textIndent === "-9000px"){
      swfDiv.style.textIndent = "0px";
      swfDiv.style.width = "550px";
      swfDiv.style.height = "400px";
   } else {
      swfDiv.style.textIndent = "-9000px";
      swfDiv.style.width = "0px";
      swfDiv.style.height = "0px";
   }
}

Using "display: none" to hide the SWF

A nice and simple solution for hiding ANY div is to use "display: none". But this method has a serious shortcoming: In Firefox 2, when you toggle the DIV back to display: "block", Firefox reloads the SWF and plays it from frame one. In many projects this can be a show-stopper.

Working examples: static publishing | dynamic publishing (tested in Firefox 2 and IE 6).

function toggleSWF(){
  var swfDiv = document.getElementById("flashcontent");
  if(swfDiv.style.display === "none"){
    swfDiv.style.display = "block";
  } else {
    swfDiv.style.display = "none";
  }
}

Using "visibility: hidden" to hide the SWF

This method works about the same as the text-indent method; when the SWF is hidden, the space occupied by the SWF remains the same. This can be useful in situations where you want to prevent the other content on your page from shifting around.

Working examples: static publishing | dynamic publishing (tested in Firefox 2 and IE 6).

function toggleSWF(){
   var swf = document.getElementById("flashcontent");
   if(swf.style.visibility === "hidden"){
      swf.style.visibility = "visible";
   } else {
      swf.style.visibility = "hidden";
   }
}

Using "position: absolute" to hide the SWF

This is an intriguging idea, but it suffers from the same problem as display: none; when the SWF is toggled to be visible, both Firefox and Safari reload the SWF and play it from frame 1. Serious drawback for many projects.

Working examples: static publishing | dynamic publishing (tested in Firefox 2, IE 6, and Safari 3.1 Windows).

function toggleSWF(){
   var swf = document.getElementById("flashcontent");
   if(swf.className == "hidden"){
      swf.className = "";
   } else {
      swf.className = "hidden";
   }	
}

</script>

<style type="text/css">
<!--
.hidden {
   position: absolute;
   left: -9999px;
}
-->
</style>

Using innerHTML to hide the SWF

Since SWFObject no longer embeds the SWF into a DIV (SWFObject 2.0 replaces the target DIV with the object element), this method is no longer relevant. However, if you're wrapping your SWF in an extra DIV and toggle the content of the wrapper DIV, you will encounter the same "reloading" problem some of the other methods encounter (the SWF starts from frame one when toggled to 'visible').