The
Use a strict DTD to enable standards mode for maximum rendering speed.
Minimize HTTP
Remove whitespace (spaces, tabs, and returns).
Omit redundant tags and attributes.
Omit optional quotes and closing tags (this can
Minimize colors and character entities.
Cut the comments.
Minimize alt values, but make them descriptive, not generic.
Minimize the head to maximize body display speed.
Minimize meta tags:
Use only the description and keywords tags.
Conditionally include meta tags for critical pages.
You can only go so far minimizing the code you use in HTML pages. To fully optimize your HTML, you've got to dig a little deeper and transform your code. This chapter shows you how to tune your tables, optimize your forms, auto-abbreviate your links, and compress your HTML for maximum speed. The last two techniques require server access, which I explain in this chapter as well as in Chapter 17, "Server-Side Techniques," and Chapter 18, "Compressing the Web."
It's too bad that tables came out before CSS. Designers who are used to pixel-level placement can be frustrated by HTML's lack of control. Some pioneers, including David Siegel, [1] with his single-pixel GIF trick, realized they could use tables as a crude layout device. The use of tables subsequently exploded.
[1] David Siegel, Creating Killer Web Sites, 2d ed. (Indianapolis, IN: Hayden Books, 1997).
Intended for tabular data, the overuse of tables has polluted the web with unnecessary presentation in billions of pages. With the
Using tables to lay out complex pages is usually a recipe for disaster. Cramming three or four
All this complexity must be parsed and unwound by your browser. That's why many sites are so slow to load, even on high-bandwidth connections. The more complex your table structure, the slower your page displays. This is
The way to speed up your tables is to give browsers as much information as possible about their structure and content, and reduce their complexity. Try to simplify, unwind, and layer your tables for speed. Use CSS to style tables, substitute background colors for background images, and use the fixed table layout option where possible to speed display. Or,
Given enough information, HTML tables are designed to render incrementally as table rows
[2] Dave Raggett, Arnaud Le Hors, and Ian Jacobs, "Chapter 11, Tables," in HTML 4.01 Specification [online], (Cambridge, MA: World Wide Web Consortium, 1999), available from the Internet at http://www.w3.org/TR/html401/struct/tables.html.
You can group rows and columns in tables to format them as a
You can group table rows into table head,
For example:
<table frame="border" rules="groups">
<thead>
<tr> ...header information...
<tfoot>
<tr> ...footer information...
<tbody>
<tr> ...first row of block one data...
<tr> ...second row of block one data...
<tbody>
<tr> ...first row of block two data...
<tr> ...second row of block two data...
<tr> ...third row of block two data...
</table>
The
tfoot
element must appear before the
tbody
tag so that the browser can render the foot before receiving all the rows of data. "This is an optimization shared with CALS
[3]
for dealing with very long tables. It allows the foot to be rendered without having to wait for the entire table to be
[3] U.S. Navy, "Continuous Acquisition and Life-Cycle Support (CALS)" [online], (Washington, DC: U.S. Navy), available from the Internet at http://navysgml.dt.navy.mil/cals.html.
[4] Dave Raggett, Arnaud Le Hors, and Ian Jacobs, "Appendix B: Performance, Implementation, and Design Notes," in HTML 4.01 Specification [online], (Cambridge, MA: World Wide Web Consortium, 1999), available from the Internet at http://www.w3.org/TR/html401/appendix/notes.html#notes-tables.
Column groups allow you to break up tables structurally and style columns with style sheets or the rules attribute of the table element.
A table contains either a single implicit column group (no colgroup specified) or one or more explicit column groups, each delimited by a colgroup element.
The col element allows you to assign attributes to one or more columns, using the span attribute for multiple columns. [5]
[5] Raggett, Le Hors, and Jacobs, "Chapter 11, Tables" [online].
You can specify the
width
attribute of columns either by using the
span
attribute of the
colgroup
element or by including it in each
col
element. Specifying multiple identically
<colgroup span="10" width="60"> </colgroup>
In contrast, here's the alternative:
<colgroup>
<col width="60">
<col width="60">
...a total of 10 col elements...
</colgroup>
In HTML 4.01, you can determine the number of columns in a table in two ways:
By using the col or colgroup elements (in that order)
If no column elements exist, by determining the number of columns required by the rows
The number of columns in a table is equal to the row with the most
Once the browser finds the number of columns, it calculates the width of each column. You can specify column widths in three ways:
Pixel A fixed width (that is, width="125" pixels ) enables incremental rendering.
Percentage Percentage widths (for example, width="33%" ) are based on the percentage of the horizontal space available to the table. Percentage widths enable incremental rendering.
Relative Relative widths (such as, width="2*" ) are based on the horizontal space required by a table. If you give the table a fixed width, browsers may still render the table incrementally. If the table does not have a fixed width, however, browsers must receive all the data before they can size the table. [6]
[6] Ibid.
By specifying the number and width of the columns in your tables, you can enable incremental rendering and speed their display. Otherwise, browsers have to wait until the table data arrives in order to allot space. Listing 4.1 shows an example.
Listing 4.1 Table Column Widths Specified
<table width="100%">
<colgroup>
<col width="33%">
<col width="67%">
</colgroup>
<tr>
<td colspan="2">
<p>top navigation bar (branding and advertising)</p>
</td>
</tr>
<tr>
<td>
<p>left navigation bar</p>
</td>
<td>
<p>main content area</p>
</td>
</tr>
<table>
Fixed or percentage widths enable incremental rendering. In the same way that authors have no control over users adjusting table and font size, relying on fixed widths can be risky, unless the content is of a known size.
You can save space by using defaults wherever possible and consolidating attributes from the specific to the global. Use one <tr align="center"> instead of many occurrences of <td align="center"> to align rows of cells. Even better, use a row group like thead or tbody to style entire blocks of rows. Listing 4.2 shows an example.
Listing 4.2 Consolidate Attributes
<table width="100%" frame="border">
<colgroup>
<col width="33%">
<col width="67%">
</colgroup>
<tr>
<td colspan="2">
<p>top navigation bar (branding and advertising)</p>
</td>
</tr>
<tbody align="center">
<tr>
<td>
<p>left navigation bar</p>
</td>
<td>
<p>main content area</p>
</td>
</tr>
</tbody>
</table>
The closing tags for row group elements and
col
are optional in HTML (
</thead>
,
</tbody>
,
</tfoot>
, and
</col>
), but required in XHTML. Note that some versions of Netscape 4 mistake the closing
</colgroup>
element for a
div
and can cause unexpected rendering behavior. Similarly, you can use
colgroup
to align one or more columns instead of aligning each individual
For example, use this to align one column:
<colgroup align="center">
Or use this to align a group of three columns:
<colgroup align="center" span="3">
This technique works for standards-compliant browsers and degrades gracefully (left aligned) for older browsers. Of course, you can use CSS instead to style your col s and colgroup s (see Listing 4.3).
Listing 4.3 CSS-Styled Table
<style type="text/css">
<!--
table#skel {width:100%;}
col#left {width:33%;}
col#right {width:67%;}
tbody#main {text-align:center;}
-->
</style>
</head>
<body>
<table id="skel" frame="border">
<colgroup>
<col id="left">
<col id="right">
</colgroup>
<tr>
<td colspan="2">
<p>top navigation bar (branding and advertising)</p>
</td>
</tr>
<tbody id="main">
<tr>
<td>
<p>left navigation bar</p>
</td>
<td>
<p>main content area</p>
</td>
</tr>
</tbody>
</table>
Let's put it all together and throw in one more table turbocharger.
With browsers that support CSS2, [7] such as IE6 and NS6, tables can get a big speed boost with the new table-layout property. The table-layout property lets authors control the algorithm browsers use to lay out the table cells, rows, and columns.
[7] Bert Bos et al., "Cascading Style Sheets, level 2 CSS2 Specification" [online], (Cambridge, MA: World Wide Web Consortium, 1998), available from the Internet at http://www.w3.org/TR/REC-CSS2/.
With the faster fixed
table-layout
algorithm, the browser sizes the table horizontally not based on cell contents, but on the width of the table and columns and any borders and spacing. This layout algorithm is faster because the horizontal layout of the table does not depend on every cell's contents; instead, it depends only on specified or default column and table widths. Thus, the browser
Here's how fixed table layouts work. For each column, the first cell whose width is not set to auto sets the width for that column.
There are three possible values to the table-layout property:
auto (the default)
fixed
inherit
For example:
table { table-layout: fixed }
col.sum { width: 10em }
The default of
auto
can be inefficient, requiring up to two
When you set the
table-layout
property to
fixed
, you are fixing the column widths (and
For CSS2-compliant browsers, this setting greatly
Listing 4.4 Fixed Table Layout Example
<style type="text/css">
<!--
table#skel {table-layout:fixed;width:100%;}
col#left {width:33%;}
col#right {width:67%;}
tbody#main {text-align:center;}
-->
</style>
</head>
<body>
<table id="skel" frame="border">
<colgroup>
<col id="left">
<col id="right">
</colgroup>
<tr>
<td colspan="2">
<p>top navigation bar (branding and advertising)</p>
</td>
</tr>
<tbody id="main">
<tr>
<td>
<p>left navigation bar</p>
</td>
<td>
<p>main content area</p>
</td>
</tr>
</tbody>
</table>
To be safe, make sure that the first row's cells are the widest in each column. If the contents of a cell exceed the fixed width of a column, the content is wrapped or, if this isn't possible, it is clipped. The CSS2 overflow property allows authors to control the behavior of content that exceeds the width of any block element, including td . Here's an example:
<style type="text/css">
<!--
table#fixed {table-layout:fixed;width:100%;overflow:hidden;}
-->
</style>
</head>
<body>
<table id="fixed">
There are four possible values for the overflow property:
visible Displays the content that exceeds the containing block (the default value).
scroll Inserts a scrollbar to the block regardless of overflow.
hidden Clips the overflowed content with the containing block.
auto Clips overflowed content and adds a scrollbar only when necessary.
I tried the fixed table-layout algorithm on Webreference.com's home page with mixed results. Listing 4.5 shows an excerpt from the source.
Listing 4.5 Real-World Fixed Table Layout
<style type="text/css">
...
TABLE#f{table-layout:fixed;width:100%}
COL#a{width:9px;}
COL#b{width:134px;}
COL#c{width:9px;}
COL#d{width:65%;}
COL#e{width:8px;}
COL#f{width:1px;}
COL#g{width:125px;}
</style>
...
<TABLE id=f WIDTH="100%" BORDER=0 CELLSPACING=0 CELLPADDING=0>
<colgroup><col id=a><col id=b><col id=c><col id=d><col id=e><col id=f><col id=g></
colgroup>
<TR VALIGN=TOP><TD WIDTH=9 BGCOLOR="#FFCC00"><IMG SRC="/t.gif" WIDTH=9 HEIGHT=1 ALT=""></
TD>
... 134 px TD follows ...
After sizing the initial cells properly, the tables flew onto the screen. However, I noticed two problems. Embedded tables sometimes moved down with unsized ads, and increasing to larger fonts caused overflow in NS6.x. Adding a
valign="top"
to the containing
<tr>
Increasing fonts to a larger size in Netscape 6.x sometimes overflowed the text in fixed columns, although reloading corrected most of these problems. IE5 Mac and IE6 for the PC seem to handle larger font sizes better. You can tweak the overflow attribute to control this behavior, although it had no effect in NS6.x. When you use a strict DOCTYPE , the overflow attribute applies to the entire HTML object.
Figure 4.1 shows what happens in Netscape 6.2 when you use the fixed table-layout algorithm and then increase the font size.
Figure 4.1. Fixed table layout in Netscape 6.2.
Increasing the initial cell size would solve some of these problems. However, Netscape 7 fixed the
Figure 4.2. Fixed table layout in Mozilla 1.0 (Netscape 7).
With fixed-width contents like graphics, use the fixed algorithm. When your content can vary in width, make sure that you test your table at larger font sizes.
I had better luck specifying widths as col attributes. Here's an example from Webreference.com's home page:
<table id=f width="100%" border=0 cellspacing=0 cellpadding=0> <colgroup><col width=9><col width=134><col width=9><col width="65%"><col width=8><colwidth=1><col width=126>
Rather than using style sheets:
table#f{table-layout:fixed;width:100%}
table#f{overflow:auto;}
col#a{width:9px;}
col#b{width:134px;}
col#c{width:*;}
col#d{width:8px;}
col#e{width:1px;}
col#f{width:126px;}
A happy medium would be to conditionally include the fixed and overflow styles for CSS2-compliant browsers like IE6+ and Netscape 7+, which is based on Mozilla 1.0. Use the colgroup and col elements for longer tables and use table-layout and overflow styles where possible.
Setting the row height can further improve rendering speed, because the browser's parser can begin to render the row without examining the content of each cell in the row to determine row height.
In those self-improvement
Browsers usually parse tables in stages. First, they look in cells to size what's inside. Then they back out of your table(s), dynamically sizing table cells along the way until the entire thing is rendered. By making your content simpler and easier to "digest," you can speed up your tables. Try removing everything that's non-essential. Take out all those cross-promo
Leave in only what's new and maybe some decks. I'll even let you leave in a logo for branding. Now your tables will really fly. You can put back in only what your users want, or better yet, let them decide. Removing excess is one of the most effective ways to speed up tablesor pages, for that matter.
The deeper you nest tables, the slower they'll display. Even after they've downloaded, browsers must perform numerous calculations to size tables properly. Complex nested tables can tax the CPUs of your users' computers, especially slower machines. Because browsers must render the deepest tables first and then back out, calculating cell sizes as they go, the trick is to unwind your tables by coding more intelligently to reduce their number and depth.
Many sites use one table to lay out their entire page. In many cases, this means the browser displays the table only after everything is downloaded and sized properly, delaying page display. The trick is to break up your tables into separate tables, like a layer cake.
Use a simple fast-loading table at the top and an above-the-fold table underneath. Include useful contentsuch as a search box or navigation barin your first table so that users can navigate quickly. Browsers render tables sequentially, so first give your users something to look at, while the rest of your page loads. This makes your pages feel faster, even though they may load slower overall. Figure 4.3 shows an example from CNET.com's home page.
Figure 4.3. CNET.com's top navigation bar.
Your first table literally pops onto the screen, giving users something to work with instantly. In Chapter 1, you learned that feedback is important. When some useful content instantly appears, users are rewarded for clicking your link. Figure 4.4 shows an example from Webreference.com's home page.
Figure 4.4. Webreference.com top navigation bar.
On the other hand, popping up useless content can annoy users. Showing them your logo or an ad quickly doesn't give them useful content and let them navigate your site. Figure 4.5 shows an example.
Figure 4.5. Onlinenewspapers.com.
A similar strategy involves rearranging tables to raise relevance along with perceived rendering speed. A typical three-panel layout has the branding and advertising in the top row, navigation in the left column, and content on the right. For an example, see Listing 4.6.
Listing 4.6 Three-Panel Layout
<table>
<tr>
<td colspan="2">
<p>top navigation bar (branding and advertising)</p>
</td>
</tr>
<tr>
<td>
<p>left navigation bar</p>
</td>
<td>
<p>main content area</p>
</td>
</tr>
</table>
Fortunately, a simple addition to the
table
element provides an alternative. Ever since Netscape 2, authors have had the ability to align tables, similar to images and modern
div
s. This feature allows you to align tables
Listing 4.7 Three-Table Layout
<table>
<tr>
<td colspan="2">
<p>top navigation bar (branding and advertising)</p>
</td>
</tr>
</table>
<table>
<tr>
<td>
<p>left navigation bar</p>
</td>
</tr>
</table>
<table>
<tr>
<td>
<p>main content area</p>
</td>
</tr>
</table>
The tables will now load individually as the HTML byte stream downloads. Now instead of waiting for one large table, the
I
The problem with these layout approaches is that your main content is buried below navigation and branding. Search engines typically look at the first 2K or 3K of your page, and give higher relevance to content toward the top of your page. There are two ways to raise your content higher in your markup: the rowspan trick and CSS2.
You can move your main content cell above your navigation by using the following markup (see Listing 4.8).
Listing 4.8 The Table Trick
<html>
<head>
<title>The Table Rowspan Trick</title>
</head>
<body>
<table>
<tr>
<td colspan="2">
<p>top navigation bar (branding and advertising)</p>
</td>
</tr>
<tr>
<td><!-- leave me empty --></td>
<td rowspan="2">
<p>main content area</p>
</td>
</tr>
<tr>
<td>
<p>left navigation bar</p>
</td>
</tr>
</table>
</body>
</html>
The trick is the empty td in the second row and the rowspan="2" in the cell next to it. The table displays the left navigation bar with the main content on the right as before, but the main content cell appears before the navigation in the markup, raising its relevance to search engines (see Figure 4.6).
Figure 4.6. The table trick.
In theory, you can omit the closing table data (
</td>
) and table row (
</tr>
) tags from your tables, because HTML 4.01 does not require them. Netscape 3 can
<table>
<tr><td>The<td>emperor
<tr><td>has no<td>close
</table>
Netscape 3 (and possibly earlier versions) can add extra space to your table cells if you put a return after a <td> . You can ensure that won't happen, while saving additional bytes, by removing returns after <td> tags, and removing other whitespace from your page. So instead of this:
<table>
<tr>
<td bgcolor="#ffcc00" align=center>
<a href="/r/ex"><b>Experts</b></a>
</td>
</tr>
<tr>
<td>
<a href="/3d/">3D</a><br>
<a href="/dlab/">Design</a><br>
...
Do this:
<table><tr><td bgcolor="#ffcc00" align=center><a href="/r/ex"><b>Experts</b></a></td></tr> <tr><td><a href="/3d/">3D</a><br><a href="/dlab/">Design</a><br> ...
By replacing background images with background colors, you can save space and a trip to the server. For example:
<table> <tr><td bgcolor="#ffcc00">...
This can, of course, also be done with style sheets for version 4+ browsers:
<style type="text/css">
<!--
.dark {background-color:#ffcc00;}
-->
</style></head>
<body>
<table>
<tr><td class="dark">
Even better, optimize the style sheet like this:
<style type="text/css">
<!--
.d{background:#fc0;}
-->
</style></head>
<body>
<table>
<tr><td class="d">
For simpler two- or even three-column layouts, you can use CSS2. You learn how this technique can save you space in Chapter 8.