Friday, 8 April 2005
While we’re on the subject…
A response to feedback in which tables and CSS for layout are compared, a discussion of the pros and cons of using frames, and a note of elaboration on the need for simpler URLs
[Editor’s note: Because this article demonstrates the “old-school” method of table-based web design, this page will not validate as XHTML 1.0 Transitional. I apologise if this creates any problems in viewing this article, and promise that it won’t happen again.]
I’ve received numerous replies to the previous article, Bad Web Design, and overall the response was positive. There were a couple points, however, that sparked some rather impassioned rebuttals. Since the points in question were also the shortest ones, I think it only fair to elaborate.
Using Tables for Layout
The arguments against using CSS for layout in favour of tables were quite a blast from the past, echoing word-for-word the arguments for the same from two or three browser generations ago.
To truly understand the complexities of this issue, it will be helpful to look at where we’ve been and where we are now. HTML and XHTML are very similar to SGML—in fact much of Tim Berners-Lee’s original HTML specification used a lot of SGML’s syntax. The idea behind SGML was that markup should be focused on the structural aspects of a document and leave the visual presentation of that structure to the interpreter, and this philosophy was imported to HTML as well. In other words, HTML itself was never meant to control the presentation of a document; only its structure. But in 1993, the NCSA started modifying the allowed properties of existing elements and adding their own elements—most notably the <img> element—to the HTML that their Mosaic browser would support. While this helped to kick-off the Web’s popularity, it was also responsible for implanting the idea that a browser maker could create its own proprietary HTML elements, which eventually resulted in the Browser Wars—a massive splintering of the Web that threatened to destroy its open nature. However, by sparking action from Tim Berners-Lee in 1994, it also resulted in the creation of the standards body known today as the W3C, which began publishing specifications for various web technologies (including CSS) and encouraged browser vendors to implement them into their browsers.
In the second half of the 1990s, browser vendors had not yet implemented CSS well enough for web developers to use it consistently and reliably. This does make some sense, however—the specification for CSS1 was published in 1996, and the specification for CSS2 was published in 1998. Despite being a web standard, the Browser Wars were in full effect during these years and Netscape and Microsoft were convinced they could only “win” by inventing new technologies at the expense of standards. (Of course, in 1998 Netscape scrapped Navigator 4 and began development of Mozilla/Netscape 6 with web standards in mind, but it took a few years to see the fruits of that labour.)
So what were web designers to do? With standards-support crippled in most browsers, another method was needed to gain interoperability between browsers. Web designers found this method in the form of tables.
Semantically-speaking, tables exist in HTML (and XHTML) for one reason: to display tabular data. But in 1996, a very influential book called Creating Killer Web Sites by David Siegel was published. This book sold incredibly well and popularised the method of nested tables with border="0", invalid background=" " attributes, and single-pixel “spacer” GIFs to control web page layout. Graphic designers loved this method because they could actually lay out a page—as many were used to in print—instead of just having everything bunched on the left or centred. With nobody yet implementing CSS into their browsers, this method became the de facto way to build web sites. Two years after Creating Killer Web Sites, David Siegel famously admitted that “the Web is ruined and I ruined it.”
As time went on, table-based layouts became more and more complicated. Tables nested within tables, spacer GIFs everywhere, and more <td> and <tr> elements than you can count. But as much as it helped the growth of the Web, the table layout method also has its drawbacks:
- It makes file sizes for pages unnecessarily large, with the user downloading all of that presentational markup for each page they visit—and bandwidth isn’t free.
- Changing an existing site’s design means hand-editing thousands of individual table cell colours, heights, and widths, or crafting new table layouts—a time-consuming and costly process.
- Pages take longer to render, as the browser has to parse all your presentational markup.
- They destroy logical document flow, and defy the most basic rule of information storage and retrieval by mixing content with appearance. Information will not always be just read by humans. A very common example is search engine “bots”, which have a harder time indexing your page when it doesn’t have a logical document flow.
- Tables-based designs usually depend heavily on assumptions about the particular viewing conditions of a visitor to the site. Screen size, screen resolution, and window size are usually put into a very narrow range, and often the layout will break if the user changes their font size in the browser.
Additionally, most table layouts aren’t using valid markup, and as Mark Pilgrim put it:
Valid markup is hard enough to debug already. Debugging Tag Soup is an order of magnitude harder. It’s also not terribly rewarding. Some of us are good at it; many of us have been around long enough to have dealt with it at one point or another. But it’s not where we like to focus our energies. There’s nothing aesthetically pleasing or intellectually satisfying about helping a hack-and-slash coder tweak their shitty markup and bludgeon a few browsers into submission. We know it’ll only break again next week; we’ve been there, we know what happens next week. We know you’re just coding on borrowed time.
And did I mention that debugging this stuff is hard? There’s a lot to keep track of, even when you do everything right. There are bugs in Windows browsers, bugs in Mac browsers, bugs in browsers old and new, bugs in Opera, bugs in Netscape, bugs in MSIE too. Dr. Seuss could make great poetry out of all the bugs we cope with in our valid, standards-compliant pages. And on top of that, you want us to keep track of the near-infinite variety of bugs that could be triggered by your Tag Soup? We don’t have that kind of time, and the time we do have is better spent elsewhere.
Consider the following snippet of markup lifted directly from Slashdot.org:
<TABLE WIDTH="100%" BORDER="0"
CELLPADDING="0" CELLSPACING="0">
<TR><TD
VALIGN="TOP" BGCOLOR="#006666"><img
SRC="//images.slashdot.org/slc.gif"
WIDTH="13" HEIGHT="16" ALT=""
ALIGN="TOP"><FONT
FACE="arial,helvetica" SIZE="4"
COLOR="#FFFFFF">
<B>Gaiman Naming Auction</B></FONT>
</TD></TR></TABLE>
This markup might look familiar to you. It might even resemble the markup on your site. In the context of this web page, all that’s actually necessary is the following:
<h1>Gaiman Naming Auction</h1>
Just put a rule in your CSS for <h1> elements and you have one rule that applies to all the top level headlines on that page, which alone will save quite a bit of bandwidth.
Of course even today a common argument is that CSS for layout is not “safe” to use, in the context of cross-browser compatibility. This may have been true years ago, but it is not true today. Modern browsers are not just newer versions of the 3.0/4.0-era browsers; they differ fundamentally from their predecessors. Mozilla, Netscape 6+, and related Gecko-based browsers are not new versions of Netscape Navigator 4. Internet Explorer 6, while still having a few bugs to work out in its CSS rendering, supports most of CSS1 and even bits of CSS2 rather well—and Microsoft has committed to improve standards support even further in Internet Explorer 7. The complexion of the Web has changed—for the better. The percentage of standards-supporting browsers in use has increased tremendously. The percentage of non-standards-supporting browsers is low and doing nothing but decreasing. According to current estimates, 4.0-and-lower browsers enjoy less than 0.5% of the global browser market share. We are now living in the Era of Web Standards. There is no need to code only for Internet Explorer or Netscape, or to use non-standard or non-semantic methods to get your sites to work in other browsers. Even today I hear things like “Using CSS positioning for layout is not cross-browser compatible; Netscape is terrible about respecting it consistently.” This is simply not true today. Netscape, thanks to its Gecko rendering engine—the same rendering engine found in many browsers today, including the popular Firefox browser from Mozilla—is incredibly consistent with its CSS rendering because it was built from the ground up to have strong standards support. In fact, more than 91% of the web browsers in use today have good-to-strong standards support, so using standards will ensure that your sites are compatible with the widest range of browsers possible, eliminating the need to put a “this site is recommended for x browser” note on your site.
And that’s not all; using structural markup in our HTML documents and CSS to lay out our pages has many advantages over tables-based design:
- It makes redesigning your sites and changing your content much less labour-intensive. To change the design of a site, all you need to do is change the style sheets—you do not need to edit the pages themselves at all. A wonderful example of this can be found at the CSS Zen Garden.
- It allows the designer to attain more precise control over layout, placement, and typography in graphical desktop browsers while allowing users to modify the presentation to suit their needs.
- It reduces the file sizes of your pages, since users don’t need to download presentational data with every page they visit. Instead, the style sheets that control layout are cached by the viewers’ browsers only once, and applied throughout the entire site. In Doug Bowman’s article, Throwing Tables Out the Window, it is demonstrated how a redesign with CSS of Microsoft’s home page would result in a 62% reduction in file size, saving 329 terabytes of bandwidth per year.
- Pages load faster, because of both reduced file size, and because when browser layout engines drop out of Standards mode into Quirks mode it tends to slow down the presentation of information as it tries to figure out all the possible side cases of all the quirks that are possible. Content that conforms to web standards can be parsed and displayed much faster.
- It is also much easier to maintain visual consistency throughout a site. Since pages use the same CSS file for their layout, they are all formatted the same. This strengthens your brand and makes your site more usable (consistency is key to good usability).
- Pages are much more accessible to users with disabilities, and to viewers using mobile phones, PDAs, screen-readers, and other devices. Separating content from presentation makes your content device-independent. And yes, even users with older browsers will have an easier time accessing the content on your page.
- Using structural markup will also improve your search engine ranking—and who doesn’t like having good page ranks?
I think Jeffrey Zeldman may have put it best in his A List Apart article, To Hell With Bad Browsers:
Thousands of new sites premiere every day. Most of them are built to support bad browsers intead of standards. It’s an epidemic. Enough already. We finally have good browsers. Let’s use them.
Let’s push these new browsers for all they’re worth, discover the remaining holes in their standards compliance, and help browser manufacturers make them even more compliant. Flash designers do this. They push Flash as hard as it will go, butt their heads against its limits, and tell Macromedia how to make it better. As a result, Flash keeps improving. Shouldn’t we be doing the same for the tools that deliver 90% of web content and functionality (i.e., web browsers)? The WaSP thinks so and ALA thinks so, too.
Now it is worth noting that sometimes we don’t always have the freedom to design pages however we want. Sometimes a client will specify the use of tables for the layout of their page. And if they’re the one signing the cheque, who are you to argue? But in those cases, you can still use tables using a transitional method that uses CSS for typography, colour, margins, and so on, while using (X)HTML tables for basic layout.
How about some examples? Here’s a fine-looking table using the old “Killer Websites” method; nested tables, spacer GIFs, invalid background=" " attributes, all of it:
| Lorem ipsum ea novum equidem ornatus his. | Ut per alia graece, docendi iracundia ne qui. Pro tritani petentium definitionem ne, quando senserit mea te. Error eirmod mea ea, nam denique dignissim omittantur et. | ||||||||||||
| Eius albucius eleifend vix ut, augue exerci vis an. | Ut nisl mollis vim, eam id commune sensibus forensibus,
vim ad odio nullam audiam. Esse illud delicata has no.
|
||||||||||||
| Nihil voluptua vim ei, ad aeque aliquid per. Diam audiam at mea, an kasd scripserit vel. | Doming ponderum vis in, sit eruditi mediocrem at, cum debet pertinacia dissentiet in. | ||||||||||||
| Eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim. | Pro utamur convenire consetetur te, eu qui labores alienum
dissentiunt.
|
||||||||||||
Let me just take a moment here to give a round of applause to my good friend Erik Hulslander for debugging that table over the course of the last few weeks to get it working. Taking one month just to get a “Killer Websites” -style 2×4 table working only helps to illustrate my point, and Erik deserves congratulations for taking the reins when I got far too frustrated with it to continue working on it. Without him, this article just wouldn't have happened. Thanks Erik!
Anyway, as you can see, that’s a pretty simple-looking, but tidy table. But under the hood, it’s a mess. 16kb worth of markup makes up that one little table. 16kb! All told, there’s 17 rows and 9 columns, and 93 instances of the spacer GIF. The dotted borders are done with a background=" " attribute that doesn’t validate. The bulletted lists are made using nested tables, and even the bullets themselves are just the • character residing in their own table cells. Nothing in this table is semantic, and at 205 lines of markup, it’s a wonder anybody would be able to make any sense of it just by looking at the page source. And all this just for a simple 2×4 table!
Now let’s try recreating that table using the transitional method mentioned earlier in the article:
| Lorem ipsum ea novum equidem ornatus his. | Ut per alia graece, docendi iracundia ne qui. Pro tritani petentium definitionem ne, quando senserit mea te. Error eirmod mea ea, nam denique dignissim omittantur et. |
| Eius albucius eleifend vix ut, augue exerci vis an. | Ut nisl mollis vim, eam id commune sensibus forensibus, vim ad odio nullam audiam. Esse illud delicata has no.
|
| Nihil voluptua vim ei, ad aeque aliquid per. Diam audiam at mea, an kasd scripserit vel. | Doming ponderum vis in, sit eruditi mediocrem at, cum debet pertinacia dissentiet in. |
| Eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim. | Pro utamur convenire consetetur te, eu qui labores alienum dissentiunt.
|
Much better! This table only takes up 4kb, which is four times smaller than the previous table. There’s 4 rows and 2 columns, and no spacer GIFs. The dotted borders are done with CSS and validate just fine. The lists are marked up as unordered lists, there’s no more fake bullets, and the markup comes in at a mere 27 lines. And there’s only 4 CSS rules attached to this table—one for <table>, one for <td>, one for <ul>, and one for <li>. Here’s those four CSS rules, for your viewing pleasure:
table {
border-bottom: 1px dotted black;
border-left: 1px dotted black;
}
td {
padding: 11px 20px 20px 11px;
border-top: 1px dotted black;
border-right: 1px dotted black;
}
ul {
margin-top: 10px;
margin-bottom: 10px;
margin-left: 0;
padding-left: 1em;
}
li {
list-style-type: disc;
margin-bottom: 10px;
}
That’s all there is. So if you have the misfortune of dealing with a client who is dead set on a table-based layout and specifically requests such, take heart. As opposed to the old “Killer Websites” method, this is the most efficient way to fulfill the client’s request, manage any amount of content and cut down on bandwidth usage (both on the host’s end and the visitor’s) while still maintaining cross-browser compatibility. While it may not be ideal, it is a method of publishing that is a reliable, cost-effective, and easy transition to web standards compliance.
But the future is about web standards, and web standards are about the separation of presentation from structure; so with the sites we make that aren’t forced into table design by our clients, why not start now? Unlike five years ago, there’s no real excuse (other than laziness) to keep us from moving to CSS-based layouts. When we use tables for layout, we lose the structural semantics of what a table is. Tables in HTML were never meant to be a layout tool—they were meant to display tabular data. Semantically marked-up pages ensure the accessibility and portability of your content to the widest range of browsers (not just visual browsers) and other data parsers, and can be easily adapted to print and alternative browsing devices—like handheld computers and cellular phones—just by linking to a different CSS file. Removing those semantics from your pages is just a bad idea. Let markup do its job—describing your content—and leave the presentation to the tool that was meant for it: Cascading Style Sheets.
Frames
A fundamental concept of the Web is that it is a unification of several abstractions in a single idea: the page. The page is the atomic unit of the Web, in the sense that the Web is a large collection of individual pages—each with its own address (the URL)—linked together via hypertext.
Frames, however, break this concept.
Frames are several pages that are added together to make one page. The typical use for frames is to put navigation or branding elements along the top and left of the content page. In theory, they make site maintenance faster and easier, and allow you to easily position your navigation and branding elements clearly on all your pages. In practise, however, they make site maintenance much more complicated. To prevent orphaned pages, for example, you need to add scripting to your site to first check if the page is in a framed context and, if not, to reload the frameset. And this is only a stopgap measure—people with scripting disabled in their browser won’t be able to have your script reload the frameset.
Another major problem with frames is that they break bookmarking. Visitors bookmarking your page expect to be bookmarking the exact page of information they’ve found, but what happens instead is that the frameset gets bookmarked. This makes it so that whenever the user wants to go back to that page by clicking on this bookmark, they have to browse through your site for the relevant page every time. Frames break the Web concept of the one-to-one map between URL and resource. The solution to this is either browser-dependent (e.g. some browsers allow you to choose the frame to be bookmarked via a contextual menu), requires more scripting built into your page, or to create a frameset for every potential combination of pages, typically one frameset per page of content.
Additionally, many search engines have problems reading frameset pages, if they can read them at all. Most resort to indexing the <noframes> content, to which most people just add something along the lines of “This site uses frames, but your browser doesn’t support them.” You can, of course, get around that problem by putting all of your content or navigation within the <noframes> elements, but that also increases your maintenance tasks, since you’re then up-keeping two sets of the same content. Even that doesn’t fix the problem that someone—after finding your site via a search engine—will still have to manually surf through your frameset to find what they’re actually looking for.
Many of the benefits of frames can be provided by using Server-Side Includes, PHP, or ASP (or some other server-side tool) instead, which allow you to insert the content of one file into other files, or otherwise dynamically create content on your pages.
It is worth noting that Inline Frames (or “i-frames”) do not have many of the problems that “normal” frames have. An inline frame is subordinate to its main page, and allows the user to bookmark the page and navigate the site as usual. Search engines also do not seem to have a problem with inline frames, making them a much better solution if you absolutely must have frames in your site.
The need for simpler URLs
First, let’s re-read what the “complex URLs” bit had:
Okay, first of all, URLs should never have been exposed in the user interface. But they’re here, and we use them. So let’s at least do each other a favour and make them easily readable. We’ve all seen URLs like this one:
http://www.amazon.com/exec/obidos/tg/detail/-/0321303474/ref=ase_htmldog-20/104-1498029-3683117?v=glance&s=booksThese URLs are generated by server-side scripts, and are by no means easy to remember or are easily typed. URLs should be concise, contain no special characters, are persistent, properly visualise the site’s structure, contain no MiXeD-case text, and be easy to remember.
The point was that if you have dynamically generated content, there are ways to make your post-data URLs better by way of URL transformations. The comment that the URL should never have been exposed in the user interface was said because in principle users should not need to know about URLs, which are a machine-level addressing scheme. But they are here and we do use them, so there are certain things we can do to make URLs more usable by the end user. Take, for example, the URL of the following article from Bound in a Nutshell:
http://discontent.com/blogs/index.php?blog=2&title=castle_in_the_sky&more=1&c=1&tb=1&pb=1
This could have easily been re-mapped to a more human-readable URL such as this, for example:
http://discontent.com/blogs/nutshell/castleinthesky/
In addition to making your readers happier, search engines—Google included—give more importance to words in URLs than they do to random strings of numbers and other characters. This means that your search rankings will be higher, which is a good thing. In short, making your URLs simpler is better for everyone—even robots.