The previous article introduced the idea of creating layers when building a website. It’s not a new concept — similar ideas have existed in computer science for decades. Even in terms of web development, the ideas are not unfamiliar. But in terms of specifics — how and why the layers are put together — the ideas are still developing.
Structure is Important
HTML is far from dead. HTML is the start of a website, the structure that defines the context of individual pages, of entire websites, and of the World Wide Web itself (for it defines the links that bind it all together). It is greatly misunderstood and maligned for perceived shortcomings. It is viewed as basic, minimalistic, and incapable of growth beyond its core definitions. Ironically enougn, it is because of its minimalistic purpose that HTML (and it’s successor, XHTML) that we can form the basics of a website.
For the sake of simplicity, I’m going to use just the term “HTML” from here on. Assume that where I’ve written “HTML”, you can also write “XHTML”.
Structure provides context. Text on a page is merely text. But with context, text is organized into elements that can be used for a variety of needs. The structure feeds into (almost) every aspect and layer of a website. At its most basic level, structure allows search engines to derive headings, lists, paragraphs, links, and meta data so they can categorize the text. Both search engines and screen readers use the structure context to know what they are reading.
I’m not going to write up a sample HTML to illustrate my point … because there’s one handily present: just view the source of this page.
Each page on this site has a specific structure, looking something like this:
- container - header
- wrapper - nav
- menu - main
It might seem like a waste to have such a high-level item such as “container”. What does it do? Why not bump everything else up a level? If you want a really good reason why something like this has value, you only need see the CSS Zen Garden. One structure, a thousand designs. The principle isn’t so much for contextualization as it is flexibility with document presentation. You could do without it, but its presence is beneficial and doesn’t take away from the technical implementation. The same principle applies with the subsections, such as “wrapper” and “menu”.
The Basics of Presentation
So your HTML structure is set, eh? Great, now you can move onto the next layer of your presentation: Minimal layout. This is meant to support earlier users that do not have an adequate understanding of CSS. This implies CSS 1.0, specifically:
- font definition (for all headers, paragraphs, lists, links, etc.)
- some colour definition (primarily for text, but some other elements are also supported in CSS 1.0)
- minimialistic layout (width and height)
Specific layout, referring to the positioning of elements on a page, is left for the Full Layout step.
The basic presentation is to provide an elegant degradable experience for those with inadequate support. Through basic support, without customization for specific (e.g. mobile) users. Similarly, basic presentation should avoid cross-browser issues inasmuch as possible. Cross-browser issues tend to arise with higher-level abilities such as positioning, which are beyond the context of basic needs.
The basic CSS should be contained in a single file, base.css, loaded using a
<link> element in HTML. Basic presentation can be enhanced and/or overridden by successive CSS files as needed. Most known agents support loading with a
<link rel="stylesheet" xhref="/styles/base.css" type="text/css" />
Care needs to be taken that these definitions are readily accessible for use in Flash. As Flash does not yet support CSS positioning, it is important that fonts and colours carry into Flash as readily as they in the Minimal Layout layer.
Now I know what you’re thinking: Am I truly suggesting maintaining TWO CSS files for a site? One with minimal layout, and one with complete layout?
Yes and no. First off, you can quite easily take your final CSS and cut it down so it’s just the minimal layout that’ll be supported in CSS 1.0 without difficulty (you might need to make some minor edits to accomodate for things like minimized attributes). With luck, you won’t need to modify your Minimal Layout very often, as it’s … well … minimal.
However, two files might not actually be enough. Especially when you’re dealing with a development team where several people might be editing the presentation. But that’s a discussion for…
With the basic presentation in place, we can look to enhancing the basic definitions with those needed for the Full Layout experience. As mentioned in [[Layered Interfaces: Setting the Stage]], support should only be for those browsers capable of handling CSS 2.1. (The list of suggested browsers is also provided in Part 1.) Although support could certainly be added for other browsers in the list, additional work will often be required to overcome compatibility issues present in those agents.
Right off the top, we can cut out the browsers that don’t support CSS 2.1 by including CSS 2.1 instructions using the
<style type="text/css"> @import url("/styles/global.css"); </style>
(As a point of note, do not try to restrict yourself to a single CSS 2.1 file. Large sites might require multiple files to adequately support presentation initiatives.)
One flawed technique to “detect” browsers is to use CSS hacks — exploiting the differences between the browsers’ capability to parse CSS. A simple intentional mistyping of CSS instructions can cause some browsers to skip over (or specifically target) specific instructions. This is an actively discouraged technique, as browser vendors tend to correct the parsing inconsistencies with successive updates, requiring active monitoring of the hacks.
The only hack I particularly like — only because it’s actually safe to use — is one that hides CSS from Internet Explorer on the Mac. This now-dead product hasn’t died away yet, and is notoriously incompatible with CSS written for other browsers. A simple edit to the
@import block does away with this rather troublesome browser:
<style type="text/css"> /* import stylesheets and hide from ie/mac \*/ @import url("/styles/global.css"); /* end import/hide */ </style>
(Thanks to Dan Cederholm for that little trick.)
No matter the specific method, the concept is the same: detect the specific browser and load a specific CSS file to compensate. This process should only be carried out in cases where it is necessary — CSS must be kept simple and maintainable.
Function after Form
<script> blocks in HTML, and even inlined with the code. It wasn’t uncommon to see image rollover code in links containing the image in question. (I’ll freely admit being guilty of all of this, incidentally.) Those were the old days … these days, we know better.
Scripts should initialize through the
document.onload() event whenever possible (some scripts do need to run during page load) to minimize interference. The obvious question is how — there’s only one event, so how do you initialize a dozen objects? Attach a method to
document.onload() that performs an
eval() on an array of methods you need to run. Simply add them to the global-defined array as the scripts are loaded, and they’ll be executed automatically.
document.onload() event fires). That’s when additional functionality can be added to the page. This can extend to rollovers, menu flyouts, animations, or windowing events — anything you can think of.
Let’s take the windowing event as an example. If you view the source of this page, you’ll see
onclick="window.open(this.href);return false" in all of the
<a> tags, and append a DOM event to open a window if a user clicks on the link.
Why extract it like this? Standards aside, there is one major reason to do so: maintenance. You can either maintain a single method that makes the call, or track down potentially thousands of instances in your HTML. You do the math…
I suppose I should throw in the obligatory AJAX comment here, too. (I hate the term “AJAX” — it’s far too misleading. But it’s also what everyone seems to know.) The same thing applies for advanced functionality — the client-server stuff I mentioned back in Layered Interfaces: Setting the Stage: keep it separate, keep your site safe.
Enriching the Experience
So you’ve built your website completely standards-compliant. Everything is wonderful. You rank high in search engines. Everyone raves about your killer Web 2.0 application.
But your boss comes up and says: “It’s fine and all … but we want to use Flash.”
Once you’ve managed to refrain from displaying your boss’ head on a pike, relax — it’s not as bad as it sounds. Your hard work isn’t going to waste, and your website is not going to lose any of its technical integrity. But it will require some forethought about your website architecture and construction to make sure your Flash layer works properly.
Okay, I’m getting ahead of myself. I keep forgetting Flash 10 isn’t out yet. Sadly, this is the future and not the present. The reality is that Flash is grossly lacking HTML and CSS support. It’s not nearly as good as it needs to be. But that doesn’t mean you still can’t integrate the two. You just need an intermediary: XML.
We need not to think of Flash so much as a stand-alone application or a separate website onto its own, but being a part of the existing website. Flash should be layered on the very top, like adding whipped cream and a cherry to the top of your sundae — in enchances the flavour and texture of the ice cream, but doesn’t replace it. Like whipped cream, Flash is rich and offers a lot. And like too much whipped cream, too much Flash can ruin an experience.
There is also the question of the Flash experience. In the standard HTTP paradigm, a request for a new page enacts a page reload — the existing page disappears and is replaced with a new page of content. Flash is not bound by this paradigm (neither is AJAX content, mind you), and there is no reason we should enforce the paradigm just because we’re making Flash a layer in our website. We should enable Flash to work with the website, but simultaneously not bind it to the website’s restrictions. We’ll do that in two steps.
Step 1: Building the Flash Layer#
Your Flash layer should be mostly empty, containing no core content. Content should be read in from an outside source to minimize maintenance. (Less material that requires editing for content changes, and the same layer can be used for multiple languages.) The Flash layer needs to be aware of the page structure so content can be easily loaded. Being able to read the CSS to set up simple formatting is also key for maintenance, but should not constrained to positioning — remember, Flash cannot understand CSS 2.1 … yet.
By the way, don’t even think about doing any of this in any version prior to Flash 8.
Step 2: Bridging the Webpage Gap#
Once Flash is loaded, there is absolutely no reason why Flash should perform like a non-Flash webpage. Put in transitions, allow animations, bring content in and out at will — break the traditional “page” paradigm! You’ve got access to all the content you need already, you just need to structure it accordingly. Oh! How about that — we already gave it structure. Convenient, non?
When the HTML structure is loaded into Flash, it also includes all the links you need to go from page to page. When a user clicks on a link to load a new batch of content, all you need to do is unload the content of the current “page” and load the new “page” content from HTML, and combine with the appropriate Flash modules. The user remains in a Flash environment, all the while seeing the new content. The bridge, when completed, should look something like this:
HTML pages need to load from one page to the next. Once in Flash, however, you can stay in Flash and just load the HTML content.
Why would you do all this? There’s a wide range of reasons, but let’s start with some of the biggest:
- Accessibility. Flash is accessible, but it requires a lot of extra work to make it truly accessible. When users who require accessible websites come to yours, they might not see the Flash … but their screen readers will see the wonderfully-written HTML that conforms to Section 508 and the WAI.
- Users who can’t see Flash. Yes, Flash has a high-90s percentage for penetration. (According to its completely unbiased creator.) But there are those users who can’t see Flash. And those who can’t see the most recent versions of Flash because they do not have the ability to upgrade — their systems are under administrative lockdown. Don’t cut them out of the experience.
- Search engines. Leave the best for last. Yes, Flash is readable by search engines. But Flash’s indexability is horrible — none of the content is contextual, so the search engines cannot weigh or rank items the same way they can index HTML. So let the HTML stand for the search engines, and make sure your Flash can load from specific pages. Voila! Deep linking.
Alright, I know what you’re thinking … that doesn’t cover everything. And you’d be right. There is one major issue in Flash that still needs to be addressed. The dreaded browser back button.
This is not impossible, and you don’t need to use framesets. You do need to use a frame of somekind, however. Luckily for us, the
<iframe> is available, doesn’t break any standards, and can remain hidden. It doesn’t interfere with search engines, and functions as the window to the history layer, allowing for back button’s functionality. As the saying goes — where there’s a will, there’s a way! For a great example of how this works, check out Yahoo! Maps Beta.
One final note to mention with regards to Flash and working with existing structure and functionality of a website: You can use Flash with AJAX, too — specifically using Flex 2. Just in case that’s of any interest…