Creating a Liquid Flash Layout for SEO

Recently I had the opportunity to start a new entirely Flash based website for a client. My first thoughts we're on the inefficiency of Flash websites for SEO optimizing and problems with indexing of content by search engines such as Google etc. to 'see' what's contained in the swf object itself, and index the site relevant to it's content.

The idea here is to create a Liquid Flash layout, that is the swf object needs to take up the entire browser width and height. So the problem would then be getting actual content markup in the associated hmtl page 'below' the swf object so it's not visible to the site visitor but there for search engines. Then robots would index the information hence not giving too bad of a hit to the page in it's rankings because of it's flash based nature.

I've used techniques before such as using CSS to hide content in similar situations, most notably using the display:none; property of the relevant content parent container, but articles abound in development communities about the potential for being penalized by Google for using this practice (see article).

So instead I decided to try and be more clever, and maybe pass some lessons learned off to other developers along the way.

Creating the Flash liquid layout

So first we need to create our actual flash file to take up the whole browser space, regardless of browser size. This will involve some Actionscript, CSS, and of course embedding the swf properly in the html. First the Flash file, create a new flash file with whatever preferences you wish for background color etc. then we're going to utilize the Stage object via actionscript in a sort of 'faux CSS' manner to control the layout of movie clip instances on the stage. First the swf object embed in your html page. I'm using the basic AC_RunActiveContent.js file that gets generated by flash when publishing your html page in flash, and won't go into the details here. Some developers prefer to use the SWFObject to embed their swf files so that's up to you. Just make sure you have it embedded properly and avoid that nasty Active-X controller message in IE for your sites visitors.

In your Flash file, go to your publish settings, make sure the html checkbox is checked, then go to your html tab and for the Dimensions drop-down, select 'percentage', and make sure the width and height are both 100%, see fig. 1. You may leave the other html publishing paramenters at their default.

What you get is similar to the script below for embedding your object, of course you will have a different path and name for your swf. But the thing to note is the way the embed is now using the height:100%, width:100% parameters in the script.

<script type="text/javascript">
AC_FL_RunContent( 'codebase','http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0'
,'width','100%','height','100%','id','path_to_your_movie','align','middle','src','path_to_your_movie',
'quality','high','bgcolor','#d8ebe2','name','path_to_your_movie','allowscriptaccess','sameDomain'
,'pluginspage','http://www.macromedia.com/go/getflashplayer','movie','path_to_your_movie' ); //end AC code
</script>
<noscript><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" 
codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" 
width="100%" height="100%" id="path_to_your_movie" align="middle">
<param name="allowScriptAccess" value="sameDomain" />
<param name="movie" value="path_to_your_movie.swf" />
<param name="quality" value="high" /><param name="bgcolor" value="#d8ebe2" />
<embed src="path_to_your_movie.swf" quality="high" bgcolor="#d8ebe2" width="100%" height="100%" 
name="path_to_your_movie" align="middle" allowScriptAccess="sameDomain" 
type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object></noscript>

Viewing the 100% Flash file in a browser

So we're almost done right? Well not quite, even modern browsers have varying ideas on what exactly 100% of the browser width actually means. Look at fig. 2, I've made my sample swf with a background color of #333, and the body with a background color of white, you'll notice the gaps above and to the sides of the embedded swf. This obviously isn't what we want so we need to clear our margins and padding on the body element via CSS before continuing.

We can clear all padding in the CSS using the universal selector as such: * { margin:0; padding:0;} also we want to explicitly set the browser height to avoid a Firefox bug, so our CSS looks like so.

* {
margin:0;
padding:0;
}

html, body {
margin:0;
padding:0;
height:100%;
}

Now no matter where your sites visitors mouse goes on your page, the browser will consider everything in the window your swf file. Literally it's taking up the entire space of the browser window as we wished. Next we'll look at the basics of setting up a the main flash content of your page using Flash and Actionscript.

Setting up the Page Layout

We have our swf embedded and taking up the entire browser width and height, next we have to consider a few important points. First, in this example, I'd like a straight forward 'box' to hold the main page content of the site that has a fixed width and stays centered on browser resize. Second, now we can no longer use CSS to style the background elements of the page we have to use Flash, but I wish to keep my page load small. Let's tackle these in order

Setting the Stage via Actionscript

We're going to use the Actionscript Stage class to take care of our layout. I would normally keep all Actionscript in a seperate file to be loaded while publishing, but for this simple example let's simply create a new actions layer in your Flash file, and add the following code to it:

Stage.align = "TL";
Stage.scaleMode = "noScale";

The first line Stage.align = "TL"; tells the swf to set (0,0) at the top left of our page, the second line Stage.scaleMode = "noScale"; is important, what it does is tell the flash movie to not scale any movie clips or items on the flash stage to fit the whole browser width as well. All movie clips on the flash stage will inherit this as well.

Next on to the interesting stuff, lets create that main content box and center it on the screen using Actionscript. In your Flash file, create a new movie clip to hold our page content, name it main_content_mc and it's important that you set the registration of the movie clip in the top center as shown in fig. 3. Also make sure to add 'main_movie_mc' as the instance name on the stage copy in the object properties box. I have a bad habit of naming my movie clips and instances the same, but I can live with it most times, plus it helps me remember where everything is.

Next we append the Actionscript to control the position of the main_content_mc by adding a listener to the stage as follows:

Stage.align="TL";
Stage.scaleMode = "noScale";

//set initial placement of main_content_mc on window open
main_content_mc._y = 100;
main_content_mc._x = Stage.width/2;

//listener functions
sizeListener = new Object();
sizeListener.onResize = function() {
main_content_mc._x = Stage.width/2; 
};
//add listener for window resize 
Stage.addListener(sizeListener);

This now gives us a nicely centered content box movie clip for our flash web site, simply looking at the above code and comments should make it's meaning pretty obvious to people familiar with Actionscript so I won't go into these basics now.The reason we used the registration mark for our main_content_mc clip at top dead center I will say though is for ease of editing the main_content_mc._y = 100; main_content_mc._x = Stage.width/2; lines. These 2 lines are what places the main_content_mc box 100px from the top of the browser window, and dead centered on window open, and the listener object keeps it centered on browser re-sizing.

Finishing up with a little 'Faux CSS' via Actionscript

Before we leave the Flash file I want to get back to what I mentioned as a potential problem from earlier. Namely that since our swf is 100% fluid now with the browser width, how do we control page layout or design? Those of you paying attention realized that the actual size of our main flash file stage is immaterial since we forced it in the embed object and Actionscript to take up the whole browser space. Similarly we can see a way now of taking any design element, turning it into a movie clip, and then using Actionscript as a means of 'Faux CSS' styling.

I created a movie clip of a basic gradient from pure white to #333 (our background color in this basic example), I named this clip (and instance as well most importantly) as 'top_grad_mc', see fig. 4. Next I'm going to add the following code to our Actionscript to complete the process of making this element stretch across the top of the browser and add some style to the page.

Stage.align="TL";
Stage.scaleMode = "noScale";

//set initial placement of main_content_mc on window open
main_content_mc._y = 50;
main_content_mc._x = Stage.width/2;

//add top_grad_mc properties to stretch across browser top
top_grad_mc.scaleMode = "Scale";
top_grad_mc._x = 0;
top_grad_mc._y = 0;
top_grad_mc._width = Stage.width;

//listener functions
sizeListener = new Object();
sizeListener.onResize = function() {
main_content_mc._x = Stage.width/2;
top_grad_mc._width = Stage.width;
};
//add listener for window resize 
Stage.addListener(sizeListener);
The final flash file

Lines 8 through 12 initiate the properties of how the top_grad_mc is displayed on the stage, this is the 'Faux CSS' if you will, things to note are that since I want to stretch my top_grad_mc across the stage I needed to explicitly set the scale property of this movie clip as top_grad_mc.scaleMode = "Scale";. I also added top_grad_mc._width = Stage.width; to the listener function to make sure the gradient changed width with browser re-size of course. You may notice I changed line 5 to read main_content_mc._y = 50; because once I got the gradient displaying, I wanted to adjust the top of the main_content_mc 'padding' if you will to look better. It looks a little more natural closer to the top of the browser window now that we have some style on the background. Note all I needed to do was change a single line of Actionscript, nice.

The way to make sure the gradient falls behind the main_content_mc (ie: appears at a lower z-index) is to have the flash layer containing the top_grad_mc below the main_content_mc layer, see fig. 5. Note I named the layers obviously for the mc's they contain.

So what was this all about again?

Whew, we now have have an extensible method of setting up and styling a basic fluid Flash based website, and you should surely be able to expand on the methods and techniques above. So let us get back to the issue at hand, putting SEO friendly content below our swf in the browser, so that it is there for parsing by the search engine robots.

You can run but you can't hide your content

Since many developers are buying Google's threats about being punished in their rankings for hiding even non-malicious content, maybe we should follow along. What I want to do is get some content in the html with typical tags to be read and indexed. I really don't trust indexing of Flash files in sites for content anyway, so here's what I'm going to do, instead of hiding the content I'm going to hide the page overflow. In essence simply use CSS to control the browser window scrolling, which used to be done commonly via javascript. This will only affect the overflow of content, since the swf object is embedded as 100% fluid.

Right below our swf object embed you used earlier on your html page
I'm going to add something like so (ignore runoff):

...
"sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
</object></noscript>
<!--Indexing Content Goes Below - Has to be manually put there of course!! -->
	<h1>Page Title goes here</h1>
	<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Mauris leo. Nam dui turpis, dapibus sed, feugiat pharetra, euismod eget, urna. Fusce interdum pede. Morbi sed nibh. Mauris vel est. Morbi vel velit. Fusce at nulla a tortor pellentesque...</p>

If we look at what happens in our browser test page before we add the appropiate CSS we see something similar to fig. 6. The wrapper div (and everything in it) is still in the flow of the html document, and pushes outside of what the browser thinks is the 100% fluid swf file. So how do we fix, we kill the page overflow by adjusting our global CSS to read as such:

* {
margin:0;
padding:0;
}

html, body {
margin:0;
padding:0;
height:100%;
overflow:hidden;
}

I added the last line to the html, body selector overflow:hidden; to kill the browser scrolling. And there it is!

Limitations

I'd say the first obvious limitation of this technique is that it requires your flash content to be vertically 'above the fold' of the browser window, at least what you expect to be the height of an open browser for the majority of your sites visitors. This is minor for most applications that would benefit from this technique in my opinion.

What about IE 6?

The technique outlined in this article has been tested in Firefox 2.0+, Opera 8+, Safari 3.0, Internet Explorer 7, and yes even Internet Explorer 6. All work flawlessly, now we just need to see if Google starts looking for overflow properties in CSS, though for the life of me I couldn't imagine why they would, fingers crossed....