Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Inheriting Web sites, Part 2: Optimizing your Web site

Take a maintainable Web site and sharpen, hone, and streamline it

Brett D. McLaughlin, Sr. (brett@newInstance.com), Author and Editor, O'Reilly Media, Inc.
Photo of Brett McLaughlin
Brett McLaughlin has worked in computers since the Logo days. (Remember the little triangle?) In recent years, he's become one of the most well-known authors and programmers in the Java and XML communities. He's worked for Nextel Communications, implementing complex enterprise systems; at Lutris Technologies, actually writing application servers; and most recently at O'Reilly Media, Inc., where he continues to write and edit books that matter. Brett's upcoming book, Head Rush Ajax, brings the award-winning and innovative Head First approach to Ajax. His last book, Java 1.5 Tiger: A Developer's Notebook, was the first book available on the newest version of Java technology. And his classic Java and XML remains one of the definitive works on using XML technologies in the Java language.

Summary:  After you've made a Web site easily maintainable (see Part 1), issues of speed, accessibility, and organization become key. Learn how to analyze your site's pages and improve their efficiency and layout.

View more content in this series

Date:  08 Apr 2008
Level:  Intermediate PDF:  A4 and Letter (65KB | 18 pages)Get Adobe® Reader®
Also available in:   Chinese

Activity:  9017 views
Comments:  

Suppose you have a Web site, and it is not something that just got dropped off as a virtual care package in your cube. You have worked with the site, it validates, and you have made sure it is easily maintainable (for more on how to achieve these goals, check out the previous article in this series). But that's not the end of the journey. Even if it is maintainable, your site can run and load slowly, it can involve files all over the file system—or, often worse, mix HTML, CSS, JavaScript, and server-side includes all in a single file—and be almost impossible to navigate. So how do you take a maintainable Web site and turn it into a slim, sleek destination for Web goers and Web designers both?

Just as there are standard tools and techniques you can use to make your site maintainable—validation, separation of CSS and HTML, organization of your stylesheets—there are also common tasks you can perform to improve your site's organization and usage even further. Some of these will improve your ability as a designer or programmer to maintain the site; some will make the site faster to access; and some will make the site easier and more enjoyable to use. All are important, though, and well worth the time you'll need to invest to put them into place.

Revisiting maintenance and organization

In the last article, you spent a lot of time getting your site's HTML and CSS to validate. You also should have broken out the style component of your page from the HTML itself. Now, it's time to revisit those decisions, do some more separation of particular parts of your page, and make sure your JavaScript is as cleanly broken out from your page as your CSS is.

HTML and CSS don't mix

Without hammering the point home (too much more), it is worth saying again that you need to pull your CSS out of your main Web page. Your CSS should be in an external stylesheet, usually named something like [page-name].css or [category/group-name].css. So you might have a page called homepage.html with a CSS stylesheet named homepage.css, or even default.css. You'll also see lots of CSS files with names like mobile.css or print.css, intended for styling documents rendered for mobile devices or printers, respectively. These names aren't just a convenience; they make finding out what's going on with your site a lot more intuitive, and that means less time spent searching around a hard drive—and therefore less frustration. The amount of productivity you'll get when you and your co-workers are quick and unfrustrated isn't really measurable, but any experienced developer or manager will tell you it is significant.

At one time, there was actually an argument that the time it took for a browser to locate and load an additional CSS file—in addition to the Web page HTML file—was a reason to avoid external CSS. Even putting aside the reality that we live in a DSL, cable modem, T1, even T3 world, this argument is silly (and that's being kind). Short of binary arithmetic, there's very little a computer can do faster than to locate a file—assuming it's on the same physical drive—and load that file as pure text when the file is just that: text. In fact, your browser spends far more time converting your Web page into a DOM tree (a tree-like organization of nodes) and rendering those nodes visually than it does loading an external text file. So use external CSS, and save yourself some headaches.

Move your JavaScript into external files

It's not about the JavaScript

If you've chosen to use VBScript, or ASP.NET, or Microsoft®'s flavor of Ajax, all of the principles discussed here with respect to JavaScript still apply. Just mentally substitute your client-side technology of choice in for "JavaScript," and you'll get the point just fine.

All of the reasons it makes sense to keep your HTML separate from your CSS are generic; in other words, it's not that CSS and HTML don't belong together, as much as it is a general best practice to keep structure (your HTML) and content (your text or data within the HTML) apart from presentation. This is called, in a loose sense, a separation of concerns. In programming circles, you'll even see a similar technique called the single responsibility principle, where it is considered good form for one software artifact (a class, or module, and so on) to only do one thing. Applying this to the Web space, an HTML file represents data; a CSS stylesheet represents styling of a particularly structured set of data. Since those are two different tasks, they belong in two different files.

The same is true when it comes to the logic in your Web pages, most often represented by JavaScript. Just as you'll often see CSS nested within style tags within the head of an HTML document (inside the head element), you'll see JavaScript within the script tag, also in the head of an HTML document, like this:

<![CDATA[
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script language="JavaScript" type="text/javascript">
/* Create a new XMLHttpRequest object to talk to the Web server */
var request = false;
/*@cc_on @*/
/*@if (@_jscript_version >= 5)
try {
  request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
  try {
    request = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (e2) {
    request = false;
  }
}
@end @*/

if (!request && typeof XMLHttpRequest != 'undefined') {
  request = new XMLHttpRequest();
}

function getImageDetails() {
 var url = "lookupImage.php?image=" + escape(getImageName(this.src));
 request.open("GET", url, true);
 request.onreadystatechange = showImageDetails;
 request.send(null);
}

function showImageDetails() {
 if (request.readyState == 4) {
  if (request.status == 200) {
    var response = request.responseText;
    var splitResponse = response.split('|');
    var title = splitResponse[1];
    var date = splitResponse[2];
    var description = splitResponse[3];

    var titleElement = document.getElementById("info-title");
    var dateElement = document.getElementById("info-date");
    var descriptionElement = document.getElementById("info-text");

    replaceText(titleElement, title);
    replaceText(dateElement, date);
    replaceText(descriptionElement, description);
  }
 }
}

<!-- and so on... there's a LOT more JavaScript here -->
</script><title>Hoverbox Image Gallery</title>

<style type="text/css">
*
{
	border: 0;
	margin: 0;
	padding: 0;
}

/* =Basic HTML, Non-essential
----------------------------------------------------------------------*/

a
{
	text-decoration: none;
}

body
{
	background: #fff;
	color: #777;
	padding: 50px;
}

#page {
  position: relative;
}

#images {
  float: left;
  width: 400px;
}

#details {
  color: #000;
}

h1
{
	background: inherit;
	border-bottom: 1px dashed #ccc;
	color: #933;
	font: 32px Georgia, serif;
        font-weight: bold;
	margin: 0 0 20px;
	padding: 0 0 15px;
	text-align: center;
}
<!-- and so on... there's even more CSS that would follow -->
</style></head>
]]>

Of course, this is the worst of both worlds: HTML and CSS up in the head. But all of this can be pulled out and placed in external files; suppose they're called hoverbox.css and hoverbox-ajax.js. Then, the nasty code above could be changed to this:

<!CDATA[
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />]]><b>
<script language="JavaScript" src="hoverbox-ajax.js"> </script></b>
<!CDATA[<title>Hoverbox Image Gallery</title>]]><b>
<link rel="stylesheet" href='css/hoverbox.css'
 type="text/css" media="screen, projection" />
<!--[if IE]><link rel="stylesheet" href='css/ie_fixes.css' type="text/css" media="screen,
 projection" /></b><!CDATA[<!endif]--></head>
]]>

Note: In this case, there are actually two CSS stylesheets, hoverbox.css (for all browsers), and a set of fixes to the CSS specific to Internet Explorer, in ie_fixes.css. For more on this particular example code, check the Resources section at the end of this article.

It's hard to say anything that is not blindingly obvious: The second example, with the CSS and JavaScript in separate files, is unbelievably easier to deal with and manage. Further, maintainability and usability are dramatically increased for designers and developers. JavaScript programmers and scripters work in one file, without having to mess with the core HTML. CSS designers can tinker in the CSS, even adding additional fixes for Internet Explorer or other browsers, without having to change the document's structure. And designers tasked with changing the HTML can do that, without having to worry about either scrolling past hundreds of lines of script and style, or changing something and screwing up not only the structure of a page, but its action and presentation as well.

The value here rises exponentially if you've got a QA (quality assurance) or testing process in place. In those situations—at least as a general rule—any file that is changed has to be re-tested. In this setup—where concerns are separated—you can change the JavaScript and test it without having to retest your style and structure. That's a huge value-add, especially when you consider that the tools and techniques used to test CSS and HTML are totally different than those used to test an interactive, JavaScript-driven Web page.

Attach event handlers programatically

There is one important difference between how JavaScript appears in a page and how CSS does. With CSS, rules are applied to elements, so it's pretty easy to get all your CSS into an external file. However, with JavaScript, things are not always so clean; JavaScript is usually not applied to an element, but to a particular event, on an element. So you'll see HTML like this:

<!CDATA[
<li><a href="#"><img src="img/photo01.jpg" alt="description" ]]>
<b>onmouseover="javascript:getImageDetails();"</b><!CDATA[ />
<img src="img/photo01.jpg" alt="description" class="preview" /></a></li>
<li><a href="#"><img src="img/photo02.jpg" alt="description" ]]>
<b>onmouseover="javascript:getImageDetails();"</b><!CDATA[ />
<img src="img/photo02.jpg" alt="description" class="preview" /></a></li>
<li><a href="#"><img src="img/photo03.jpg" alt="description" ]]>
<b>onmouseover="javascript:getImageDetails();"</b><!CDATA[ />
<img src="img/photo03.jpg" alt="description" class="preview" /></a></li>
<li><a href="#"><img src="img/photo04.jpg" alt="description" ]]>
<b>onmouseover="javascript:getImageDetails();"</b><!CDATA[ />
<img src="img/photo04.jpg" alt="description" class="preview" /></a></li>
<li><a href="#"><img src="img/photo05.jpg" alt="description" ]]>
<b>onmouseover="javascript:getImageDetails();"</b><!CDATA[ />
<img src="img/photo05.jpg" alt="description" class="preview" /></a></li>]]>

This could go on and on. In this case, there were 20 images in a gallery, and each had that onmouseover event handler. At first blush, this seems a necessary evil—just part of attaching JavaScript to events. And, if you've got a single event that needs to call a single JavaScript function, that's probably okay (for instance, clicking a particular image calls the JavaScript function returnToHomePage() or something). However, in cases like those shown above—where a large number of images or objects all are attached to the same JavaScript function—you end up really cluttering your HTML page.

Avoiding this, though, is not that hard, and it just takes a little more JavaScript. That, of course, means you can put the extra JavaScript in your external file, and forget about it—separation of concerns again. All you really need to know is what makes the elements you want to attach event handlers to unique. For instance, in the code above, suppose I wanted to make a change and attach all those mouse event handlers to the images in the "preview" CSS class, and also to change the event from onmouseover to onClick (that's actually what I ended up doing in that code in the article). In that case, I'd need a JavaScript function like this:

function addImageHandlers() {
 var imagesDiv = document.getElementById("images");
 var imageElements = imagesDiv.getElementsByTagName("img");
 for (var i=0; i<imageElements.length; i++) {
  var class = imageElements[i].className;
  if (class == 'preview') {
   imageElements[i].onclick = getImageDetails;
  }
 }
}

Most of these details are page-specific, and this article is not focusing on how to programatically assign event handlers. In a nutshell, though, this grabs all the img elements in a particular div, named "images", and then finds all those images in the "preview" CSS class. Finally, I use the onclick handler and assign it the method I want to run on that event: getImageDetails(). The result is that I can ditch all those event handlers on the HTML img tags.

The only downside is you'll need to run this method on your page's onLoad event, on the body tag. Still, you've abstracted all those individual image handlers out. And, most important—and not so obvious—you can change what elements have events assigned to them in your JavaScript file, and not touch the HTML. Suppose you wanted to use the onmouseover event again, or different elements; just change the addImageHandlers() function, and you'll never open your HTML. That's a win.

In fact, you may want to start having your page always run a utility function, something like initPage(). You could then put anything you needed to in that JavaScript function, adding, removing, or changing event handlers, and never open your HTML. The more separation of concerns, the less testing of unchanged components of your page, and a lot easier way to update your Web pages.


Server-side includes: The odd man out

Suppose you get your CSS out of your HTML, your JavaScript into external files, and you even manage to consolidate almost all of your event-handler assignments to a single method on your page's body tag, in the onLoad event. You're done with the programming part of your page, right? Unfortunately, not yet. You've still got one thing to worry about: server-side includes (commonly referred to as SSI or SSIs). They usually look like this:

<!--#config timefmt="%A %B %d, %Y" -->Today is <!--#echo var="DATE_LOCAL" -->

This would simply print out today's date in the specified format.

Server-side includes are a bit of a one-off these days; you'll either use them a lot, or you won't at all. In other words, you'll find pages that use them all over the place—for time stamps and last-modified dates and counters and headers and footers and ... well, the list goes on and on—or you won't find them at all. In fact, you'll rarely ever find a site that uses between one and twenty SSIs; most sites either avoid them entirely (that's a big zero), or use them like crazy.

Are SSIs bad or evil?

There's nothing wrong with SSIs. Most programmers today prefer to go with a newer scripting language, like PHP, JSP, or ASP (depending on your vendor or technology of choice), but SSIs are often an easy way to get little bits of functionality into your Web page without much work.

However, SSIs can become a problem when they're over-used. Take, for instance, using a standard footer, perhaps with a color bar, a set of contact links, and a copyright. You can include that in the bottom of each page of your site like this:

<!--#include virtual="/footer.html" -->

But that's pretty handy, so maybe you could construct a common header, too, and start including that in your documents. And navigation is usually common, so maybe SSIs work for that, as well. (Although your navigation is going to change slightly based on the current page, so maybe the included page with navigation links also uses some SSIs to implement a little display logic.) And you might want to list the last few blog posts, or the last few updated pages, or maybe just run another script that loads a cookie and offers a personalized greeting. SSIs work for all of this.

The problem is that at each step, you're incurring overhead. You're keeping up with more and more small files—which is okay—but also building a set of undocumented assumptions. Every page must include a header and footer, and be in a certain directory (or make changes to the SSI includes to point to the right directory where the included files live). It quickly becomes a big deal. And, perhaps most important of all, you're treating SSIs like a scripting language to build dynamic pages. That is not what SSIs are best at; instead, they're good at little bite-size bits of functionality.

Scale your SSIs back

If you are trying to make a site better, (more) maintainable, and designer- and developer-friendly, consider pulling out as many SSIs as is reasonable. If you need one to pop in the current date, that's fine. If your page is little more than a combination of SSI includes and logic between angle bracket comments (<!-- and -->), consider simplifying your site, or going to a full-blown Web scripting language, like JSP or PHP.

Additionally, if you are already using PHP or ASP.NET or JSP, then you should pull all the SSIs out of your page. Once you've made the plunge—in both time and expertise—into a scripting language, go with that. You'll have the same amount of overhead, but you'll also have one less technology in your stack to keep up with. HTML, CSS, JavaScript, and your scripting language are more than enough without adding SSI to the mix.


Organizing your site's files

If you've been following along, and especially if you've had a site with pages that combined HTML, CSS, and JavaScript, you've solved lots of problems—and potentially created some new ones. Once you start to separate your structure (HTML) from your presentation (CSS) and your actions and behavior (JavaScript), you have lots of separate files ( HTML, CSS, and JavaScript) that are strewn all over the place.

Of course, that's all in addition to the normal glut of files most Web sites have: HTML pages for ten, a hundred, even five hundred different pages, potential header and footer and navigation support files, images, text files, more images (you get the idea). And while loading a file three directories down and one directory over doesn't take much time, finding that file sure can. Once again, organization is key, and taking a little time to organize your site is critical if you want it to hold up long-term (which is to say, beyond a long weekend when you sleep twice and forget where everything is).

Organize files globally by category and type

The most common layout option—short of just chunking everything into a directory together—is organizing all your files by type, off the root directory of your site. So you'd have, for example, an images/ directory, a css/ directory, maybe a js/ or scripts/ directory, and then all your HTML files go in the root. So all your documents have paths like images/header.gif and css/default.css.

This is a great first step, because you immediately know where your images are—in their own directory. And your CSS is in its own directory, too. Scripts? Same deal. It's an easy way for you or new designers and programmers to organize things, and it's completely self-documenting. No explanation or lengthy documents are needed to get the idea across.

There's another subtle advantage, if you follow a pretty common practice to store HTML files in sub-directories. Suppose you've got a blogs/ directory where you keep all your HTML blog posts, and a music/ directory for all your reviews on CDs and concerts. With all your images in an images/ directory off the root of your site, you don't have to use relative paths src="local-image.jpg" in your img tag, as opposed to src="/images/image-name.jpg".

More importantly, as you start to include headers and footers from stock templates, and you've got a file in your blogs/ directory that includes footers from your site's root (or, even better, a templates/ directory), you don't have to navigate confusing path structures. All your paths start from the site root (/), and go forward. This avoids your having to keep up with what directory you're in, and even better, nasty paths like src="../../images/logo.png".

The downside of this approach, though, is that all your images are in one place; all your scripts are in one place; and all your CSS is in one place. Yes, that was the upside, too, but inherent with a single place means you could have name collisions. What happens when you store full-moon.jpg in /images/ to go with your musing late night blog post about New York, and then six months later, store full-moon.jpg in /images/ when you catch an embarrassing shot of your brother-in-law at a frat party? Well, let's just say that anyone that comes to your blog post about a nice night in Manhattan is going to be a bit surprised at what they see.

That's a classic case of a name collision: two files in the same location attempting to share a name. If you keep everything together by category, you're going to have to be extra-careful about not overwriting old files with newer files that have the same name. Otherwise, you've got the moon-problem—and nobody wants that.

Nest organizations by site groupings

A second approach, slightly more refined than global categorization, is to take the entire concept of categorization and apply it recursively. Suppose you have four sections of your site: products, documentation, support, and an FAQ. You'd create four directories in the root of your server, maybe products/, docs/, support/, and faq/. Then, you'd apply the categorization approach to each of these directories.

So in products/, you'd have an images/ directory, a css/ directory, and scripts/ directory, and so on. And all the CSS, JavaScript, images, and resources for products would live in that sub-directory. In essence, you've created a products mini-site. Then, the same would apply for the other three directories. You'd have images and scripts and so on for each, all stored within that sub-site's directories.

Organizationally, this is a lot easier to work with. If you're working on a product page, all of your resources are in that directory. And, maybe even more importantly, all the resources for the other pages are not in the products mini-site. So you've got fewer files to work with, and all those files are relevant to what you're working on.

Finally, this makes name collisions a lot easier to avoid. You're working with a smaller set of files, and the chances of using the same name are reduced. That doesn't mean they can't happen, but with fewer files, it's even feasible to manually check before you replace or overwrite files with the same name.

Of course, the downside here is that you can easily duplicate some resources. What happens if all the pages on all of your "mini-sites" use the same footer, or header, or logo? Suddenly, the mini-site breaks down, or at least gets complicated. Of course, the answer isn't profound; it should be pretty obvious.

Using a hybrid between global and sectional groupings

It turns out that there are really two levels of categorization that you'll need to put together a sensible physical layout for your site. First, you need to figure out anything in your site that is global: that cuts across two or more of your mini-sites. So if you've got footers for your entire site, or a common logo, or maybe a CSS stylesheet that all your pages use, those are global resources. They shouldn't be nested within sub-directories, because all your pages need them.

Then, once you've figured out your global resources, put them in categorized sub-directories in your Web server's root. So you'd have global stylesheets in /css/ and scripts all pages need in /scripts/. Then, apply the same mini-site approach as before: separate into sub-directories, and put resources used by only a particular mini-site into the relevant sub-directory (still in images/ or scripts/ or whatever is appropriate).

If you take this approach—and it's one of the most common used by Web professionals—you really get the best of both worlds. You've reduced the number of files in one place by segregating your mini-sites, and you've made it reasonably possible to avoid name collisions. But you've also reduced duplication of resources, so mini-sites that share files just use that file once.

There is one choice you'll have to make, though: whether, when referring to global files, to use the "../" notation (as in ../images/logo.jpg), or absolute path notation (as in /images/logo.jpg). You'll be much better off avoiding all the ../ type of stuff (which will quickly turn into ../../ and even ../../other-section/images). If you've followed the hybrid approach, you'll have images specific to your local mini-site in paths like images/blog-header.gif and global images in paths like /css/default.css. That's a very easy distinction to see and appreciate, and still manages to be self-documenting. The result is, again, an easy-to-understand HTML page, from within or without. And that's good for you, your team members, and anyone else who has to work with your pages.

Avoid the big bucket approach

Whatever approach you take, there's really only one patently wrong one: the big bucket approach, where you throw everything into one directory. You can usually spot these setups via the public_html directory, used commonly by starter sites or GUI tools. While neither starter sites or GUI tools require you to organize things this way (that is to say, not organize things), it's often simpler for someone to simply leave everything lying just where their GUI editor or FTP tool puts them.

The most obvious problem with this approach is that the number of files on your system often grows exponentially as compared to the number of pages. So one page often refers to two or three other pages, five or ten images, maybe a CSS stylesheet and some JavaScript—even with shared resources like common stylesheets or JavaScript files, things get out of control quickly. And, really, you went to all that trouble to organize your individual HTML pages, so why not apply the same principle to your site's physical layout?

There's also the same problem as mentioned in the section on grouping everything globally by category: name collisions. You drop an image into a directory with hundreds of other images—let alone hundreds of other files of all types—and you're going to have to cross your fingers. Sure, you could just do a simple ls or dir, but most folks that don't spend time organizing their site's physical layout also don't take the time to take precautionary steps like that. The result? Overwritten files, images (or CSS or JavaScript) mysteriously "changing", and pages going haywire in totally different sections of the site than you expected.


Streamline your CSS

CSS is one of those places where it can take a lot to do a little, or take a little to do a lot. By applying a few rules site- or at least page-wide, you can get great effects, but by applying a lot of specific rules, you can get an incredibly detailed, stunning page. The problem is that with all those global rules, the pseudo-selectors, the styles that only apply to an image in a paragraph element tagged with the "i-hardly-ever-appear" class, you can start to have CSS bloat. CSS bloat is when you have rules in your sheet that are never used—bad, but not awful—or rules that contradict or override each other—really annoying, and potentially a big problem. Your job, with a well-organized and maintainable site, is to get rid of both.

Ditch unused rules

You should already be running your pages through the CSS Validator (see the Resources section for links to both the HTML and CSS validator, as well as the previous article in this series, which details use of the CSS validator). That will highlight most of these problems, even though the actions to take aren't made as clear. First, if you validate a page and find that several of your CSS rules aren't used, don't immediately assume you can delete those rules! As you build stylesheets that are used by multiple pages, or even an entire site, you're going to have rules that apply to only a subset of your site's pages. You could argue that only rules that apply to every page of a site belong in a site-wide CSS, but that sort of logic sounds better in print than it does in practice.

This is where some brute force and tedious work comes in. You're going to have to run through at least a large sampling of your site's pages to find out if any rules aren't used across your site. Try at least ten pages, and for each, try and note down which rules aren't used (the rules unused are usually a much smaller set than those that are used). Then, once you've got a good sample, see which rules don't appear in any of your pages. Try commenting them out in your stylesheet and see what happens. Of course, with CSS rules trickling down, and a site that has a hundred or more pages, the only way to really test this out is to try every page on your site, and see if anything looks funny.

And it's worth pointing out that, unfortunately, sometimes the benefit here isn't worth the effort. Your pages won't load any faster, although your CSS will be cleaner and a better representation of what's really going on in your site. In most cases, the best solution is to try and remove any obviously unused rules. But if you've got ten CSS stylesheets used across your site, or a single stylesheet with hundreds of rules, you might want to get rid of the obvious offenders and call it a day.

Omit overlapping rules

Trying to root out rules that overlap and override each other is even a more labor-intensive task. It's simply a matter of building—on paper, in your head, or with a tool (if you find one, let us know!)—the hierarchy of how your CSS is applied to your page. For example, if you've got any global rules that apply to an entire page, that's at the top of your hierarchy. Then, any rules that apply to, for example, your page's body tag, or maybe a p tag. Then, rules that apply to certain p tags, or divs. And so on. You'll end up with a cascade—the same sort of cascade your browser applies. Rules at the top are applied, then rules below them, and on through your page and stylesheet. More specific rules override more generic ones. So a rule that applies to links within the "guitars" div that have the "acoustic" class are going to replace and override tags that are set for the entire page.

The problem here is that it's really, really tedious to both build and analyze this hierarchy. You've got to see what's applied to your entire page, and then make sure that there are elements that none of the other rules apply to that are affected by your topmost rule. In other words, if no element is styled by a high-level rule, because more specific rules are always in effect, then you should get rid of that unused rule.

For example, suppose you've got a CSS rule like this:

body {
	background: #fff;
	color: #777;
	padding: 50px;
}

But then suppose your site's policies (that are documented and explained to your entire team, right? Or at least, if you're a solo developer, you've got them scrawled on a sticky attached to your monitor?) dictate that all pages maintain their content in one of four div elements: a div for the header, one for the footer, one for navigation, and one for content. Each div has an id that identifies which function it serves. So maybe you've got some additional rules, like this:

body {
	background: #fff;
	color: #777;
	padding: 50px;
}

<b>div#header {
	background: inherit;
	border-bottom: 1px dashed #ccc;
	color: #000;
	padding: 50px;
}

div#nav {
	color: #888;
	padding: 50px;
}

div#footer {
	clear: both;
	font: 10px Verdana, sans-serif;
	padding: 10px 0;
	text-align: center;
	color: #000
}

div#content {
	background: inherit;
	color: #777;
}
</b>

The problem here is that if you put all your page in one of these four divs, there's never a time when the color: #777; rule in your body selector gets applied without being overridden. Each div has its own color rule that overrides the body selector. But how do you find these things? Lots of trial, error, and sometimes a little luck. So you'll have to decide for yourself what it's worth to find and remove these instances.

However, there are some real advantages here: By moving as many rules as possible to the most specific element that rule can be applied to means your overall page has fewer rules. That, in turn, means that if you add new content, you don't have to wonder why it suddenly appears in pink text with a wild font. There probably won't be lots of rules that apply to it, because it's not tagged with an ID or CSS class or inserted into a styled element. Simpler is better, and means you can get right to designing, rather than undoing, other rules that are applied to your new content.


Is your dynamic page really dynamic?

So far, we've talked about all the components of your page as if they're all necessary. If your page had SSIs, you either made sure they were sparse, or possibly converted them to another scripting language—but there wasn't any real analysis of whether that SSI was serving a useful purpose. The same went for your CSS, your JavaScript, all your images, and so on. If it was in your page, it must be right where it should be, right? Well, maybe.

Do you really need that timestamp?

In most cases, the most time-intensive part of processing any Web page is dealing with dynamic information in that page. Whether it's pre-loading image rollovers or initialing an XmlHttpRequest object for a later Ajax request or assigning event handlers, it's your code that takes time. Browsers are great at rendering HTML, and even pretty good at loading images these days, but any sort of server processing takes time. Every server-side include has to be processed, every JavaBean in your JSP (JavaServer Pages) tags, and every macro in your VBScript has to be processed and executed. That all takes time, and often means your page isn't rendered as quickly in a user's browser.

And here's where you have to take off your programmer or scripter hat, and put on your user hat. Does everything in your page that takes time to load—especially server-side includes and JavaScript that loads when a page does (that's usually found in the onload event on the body tag)—make your page better? Even more to the point, does it improve the user experience? Because if it's only there as a frill, or a "it's really cool" item for you to show your buddies, it's got to go.

Time stamps, date stamps, the last page modified, the date and time a page was last modified—all of these might be unimportant components of your Web page that you can easily remove. If so—if you can say that your users really don't need these things—then you serve your users and your pages well by removing them. Your page load time should decrease, and you've ensured that your pages only contain what they need.

Also avoid over-zealousness

Before you go slashing all the functionality of your user pages, a word of caution is in order. Yes, you'll decrease your page's load time, and yes, you can remove frivolous scripts and interactive bits from your pages, but sometimes you do need some interactivity. And, sometimes, a time stamp or last viewed stamp does matter.

A lot of times, developers find that they can greatly simplify their pages by taking out all the little SSIs or onclick and onmouseover events. Usually, this is a good thing, and leads to slimmer and meaner pages. But, things can also get out of hand. Take enough away, and your dynamic pages may end up not only trim, but flat out boring. Remember, the question to ask—and answer—is, "does this improve the user experience?" And while it is important and helpful to remove something if the answer here is "no," it's just as important to leave something in if the answer is "yes."


Conclusion

As is the case most of the time on the Web, simplicity is often the antidote to most ills. If your site is large and unwieldy, you may need to reorganize its physical layout into simpler mini-sites. If your pages are a mess to edit, update, and maintain, you may need to break out your CSS and JavaScript. If SSIs are all over the place in your pages, the simplest thing is to often cut the SSIs out. If you've got rock-solid pages that just seem to take a while to load, consider cutting little bits of so-called interactivity that are nothing more than eye-candy or nice-to-haves that really don't improve the user experience.

In all these cases, though, don't take any action without thinking how it affects your user's experience first, and your work environment second. If something makes it easier to maintain and work on your site, but also makes your pages look clunky or turns them into an unnavigable mess, you've got to deal with the effort and keep your pages easy-to-use. But if you improve the user experience, or even keep it just as it is, but can improve how easy it is to find files, or change behavior, or sort out the tangled links in a page, then you've done yourself a favor.

Ultimately, the goal is to find a problem, isolate that problem, and fix it. Then, your job isn't done; you have to see if that change improved the site, left it the same, or made it harder to use from an outsider's perspective. Only if the change still looks good from the user's perspective can you keep it in place. And, bit by bit, small change by small change, you improve your Web site. Along with this, when you make changes to a site's look or functionality, you have to keep this approach intact. If you or other developers or designers toss out all these principles when you're working on new content, your site will continue to flip back and forth between maintainable and a big pain—and you'll spend most nights with a headache.


Resources

Learn

Get products and technologies

  • Head First HTML with CSS & XHTML (Elizabeth and Eric Freeman, O'Reilly Media, Inc.): Learn more about standardized HTML and XHTML, and how CSS can be applied to HTML.

  • JavaScript: The Definitive Guide (David Flanagan, O'Reilly Media, Inc.): Includes extensive instruction on working with JavaScript, dynamic Web pages, and the upcoming edition adds two chapters on Ajax.

  • Download IBM product evaluation versions and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.

Discuss

About the author

Photo of Brett McLaughlin

Brett McLaughlin has worked in computers since the Logo days. (Remember the little triangle?) In recent years, he's become one of the most well-known authors and programmers in the Java and XML communities. He's worked for Nextel Communications, implementing complex enterprise systems; at Lutris Technologies, actually writing application servers; and most recently at O'Reilly Media, Inc., where he continues to write and edit books that matter. Brett's upcoming book, Head Rush Ajax, brings the award-winning and innovative Head First approach to Ajax. His last book, Java 1.5 Tiger: A Developer's Notebook, was the first book available on the newest version of Java technology. And his classic Java and XML remains one of the definitive works on using XML technologies in the Java language.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development, XML
ArticleID=300170
ArticleTitle=Inheriting Web sites, Part 2: Optimizing your Web site
publish-date=04082008
author1-email=brett@newInstance.com
author1-email-cc=dwxed@us.ibm.com