Improve Drupal web site performance by simplifying the site's theme

Technologies: Drupal 5+

A web site's theme includes CSS files to style the site and images to add decoration. Improve Drupal web site performance by simplifying the theme to use fewer styles and images.

Introduction

Drupal 5's default theme is "Garland", which looks nice but it includes a big style sheet and multiple decorative images. These take time to send to visitors of your site. While the files can be cached by the visitor's browser, that first visit to the site is still slow. Unless your visitors come to your site frequently, your CSS and image files won't stay in the browser cache long enough and your visitors will have to download them all over again on the next visit, and the next, and the next. Soon enough they will tire of long download times to visit your site. First-time visitors may not tolerate it at all. To make a good first impression, and to keep your repeat visitors happy, it is important to keep page load times as short as possible by reducing the amount of CSS and image data that they have to download.

Usability studies have found that visitors are impatient. They expect a fast response from every site they visit. With a page load time under 1 second, visitors find the experience fluid, but if the load time increases to 4 seconds, retail visitors begin to leave for a faster site. If times stretch to 10 seconds, most visitors will give up on your site. So, there's our goal: a download time under 4 seconds at all costs, and preferably at or under 1 second.

This article looks at the page load times of the standard Drupal themes and at what makes them fast or slow. It provides guidelines on how to simplify a theme to achieve better first-visit performance and achieve fast load times, even when serving the site over a cable modem or DSL connection.

Step 1: Enable all system-wide performance improvements

Before worrying about theme speed, first enable all of the caching and compression features of Drupal, MySQL, PHP, and Apache. This gives you a fast starting point for further optimizations:

The table below shows page load times for our simple and complex test web sites (see Specifications for Drupal web site testing). These times are for loading the site's home page for a first-time visitor where none of the site's CSS or image files are in the visitor's browser cache. The Charles proxy server is used here to throttle speeds down to the 64 Kbytes/sec common for sites served over a cable modem or DSL connection.

Test Simple site Complex site
Unoptimized 10.473 sec
(100%)
20.676 sec
(100%)
+ script cache 9.412 sec
(90%)
18.060 sec
(87%)
+ query cache 8.709 sec
(83%)
14.748 sec
(71%)
+ page cache 6.725 sec
(64%)
10.527 sec
(51%)
+ CSS aggregation 5.819 sec
(56%)
8.278 sec
(40%)
+ text compression 3.197 sec
(34%)
3.678 sec
(15%)
Page load times with essential performance improvements

Without optimizations, the visitor's page load time is 10-20 seconds. This is very bad. Few visitors would bother waiting that long. With optimizations, the load time is under four seconds. That's a huge improvement, but we still need to get to one second to make the site feel snappy and responsive.

Beware of calling "under four seconds" good enough. The times above were performed on a dedicated network without competing traffic from the rest of the Internet, and without DNS host name lookups. Your site visitors don't have it that good. DNS lookups and Internet traffic can easily add several more seconds to the page load time. To keep the visitor's load time below four seconds, your site needs to be down to one or two seconds on its own.

Also note that Drupal's page cache only works for anonymous visitors. Logged-in visitors get custom-built pages, bypassing the page cache. In the table above, the page cache reduced load times by 2-3 seconds for our test sites. Add those seconds back into the load time once a visitor is logged-in. Since even logged-in visitors deserve short load times, your site needs to be under four seconds even with the page cache disabled.

Step 2. Use a simpler standard theme

A theme adds one or more CSS style sheets and images for page decoration. These take time to load into your visitor's browser. The table below lists the standard Drupal 5 themes and the number and size of the files they add to a page.

  CSS Images
Theme # Size # Size
Blue Marine 1 5,668 1 1,767
Chameleon 2 3,844 2 1,962
Garland 3 19,083 15 15,160
Marvin (Chameleon fixed) 1 3,128 2 4,426
Minnelli (Garland fixed) 4 19,420 15 15,160
Pushbutton 1 12,348 27 30,150

Drupal's default style sheets also include decorative images.

  Images
  # Size
Drupal defaults 10 5,001

The default "Garland" theme in Drupal 5 has a lot of CSS and images. "Minnelli" and "Pushbutton" are as bad or worse.

Fortunately, theme images only load if they are needed on a page. For example, "Pushbutton"s forum background images are only loaded if the page contains forum content. The most important images in a theme are the ones that must load for every page, such as header and general page backgrounds.

The table below reports page load times for our simple and complex test site home pages for the standard themes. Site optimizations remain enabled from step 1. The slowest themes are the ones with a lot of CSS and images, like "Garland" and "Pushbutton". The simpler themes have half the page load time.

Theme Simple site Complex site
Blue Marine 1.540 sec 2.445 sec
Chameleon 1.578 sec 2.199 sec
Garland 3.197 sec 3.678 sec
Marvin 1.713 sec 2.272 sec
Minnelli
4.174 sec 4.271 sec
Pushbutton 3.239 sec 4.017 sec
Page load times for different themes

Step 3. Disable unused theme features

Drupal enables all themes to include a logo icon, a "favicon" for browser favorites lists, and text for a slogan and mission statement. Do you really need all of these? You can enable and disable these in Drupal's configuration pages:

  1. Log in as your site's administrator.
  2. Go to the "Administer" page.
  3. Select the "Themes" page under "Site building."
  4. On the theme list, select the "configure" link to the right of your theme.
  5. Check/uncheck features on the theme.
  6. Save the configuration.
  7. Reset your Drupal page cache (it doesn't reset on configuration changes):
    1. Select the "Performance" page under "Site configuration."
    2. Disable the page cache.
    3. Save the configuration.
    4. Re-enable the page cache.
    5. Save the configuration.

Chances are you'll want your own logo image instead of the default Drupal "drop" icon. Remember to keep the logo small and heavily compressed.

By default, Drupal enables a mission statement, but leaves it blank. Save a tiny bit of Drupal effort by disabling the slogan and mission statement. Most people skip these, or include them within the logo image.

The shortcut icon, or "favicon", is also optional. Some browsers use it in favorites/bookmarks lists. Though only 16x16 pixels, the icon's file format doesn't support compression, making the icon file about 1 Kbyte. Worse, some browsers (like Firefox) actually load the icon twice for every page. If this icon isn't a vital feature for your site, turn it off to save page load time.

  1. Don't uncheck "Shortcut icon" on the theme configuration. You'd think this would work, but it just forces the browser to default to looking for "/favicon.ico". If the file doesn't exist, the browser gets a 404 (not found) message on every request for the icon. And that actually takes more bytes than the icon file did, and it adds an entry to your web site's error log.
  2. Instead, leave "Shortcut icon" enabled but uncheck "Use the default shortcut icon".
  3. Type a "/" by itself as the "Path to custom icon". Browsers recognize this as meaning there is no favorites icon.
  4. Save the configuration.

Step 4. Create your own theme

Keep in mind that (1) you can download other free themes from Drupal's web site, and (2) you don't have to use any of them as-is. If you create your own theme, you can craft the look you want and use an amount of CSS and image data that makes sense for your site's network bandwidth. To create a new theme, copy an existing theme and start editing. The "Blue Marine" theme is a good starting point.

Here are a few things to keep in mind when creating your own theme...

Don't depend upon the browser cache

An often-repeated excuse for using big images is "It's OK because they'll be cached by the browser." Yes and no. Your site might be great, but it is unlikely that it is the only one your visitors go to. The files from other sites, along with yours, are all added to the visitor's browser cache. If they don't all fit, then the oldest files are deleted to make room for new ones. If someone visits your site in the morning, by that afternoon your files are probably long gone from their cache. If they return to your site, they'll have to download them again. And so on, every time they return to your site. A browser cache mostly only helps if a visitor views several of your pages in quick succession before going elsewhere.

So, don't depend upon your files being in the browser cache. They probably won't be. Instead, make your site fast by using small CSS and image files. It'll be even faster if the files do happen to be in a frequent visitor's browser cache.

Use a single CSS file

During theme authoring, it can be convenient to split CSS into several files - perhaps overall layout goes in one CSS file, menu decorations in another, and background decoration in a third. This is handy during editing, but don't leave it this way. Drupal's CSS aggregation feature can only aggregate the main "style.css" file for your theme. Any files you include with CSS "@import" lines won't get aggregated. This forces your visitor's web browser to ask for each of them individually, which takes time.

For example, in the table in step 2 we compared the "Garland" theme with it's "Minnelli" derivative. The "Minnelli" theme uses a short "style.css" file with an "@import" line to include "Garland"s main style sheet. That one "@import" line prevents CSS aggregation and adds almost one second to the page load time. Other than this "@import", the two themes are practically identical.

So, put all your CSS into one "style.css" for your theme. Don't use "@import".

Don't duplicate CSS default styles in Drupal and HTML

Some theme authors brag that they like to copy all of Drupal's separate theme files into one big file, then tweak everything for their ultimate theme. This works, but remember that Drupal's own CSS files get downloaded anyway. If your theme has a copy of all of them, you've just doubled the CSS download size for your site.

Instead, keep your theme's CSS file brief by only including things that are different from the Drupal and standard HTML defaults. Don't duplicate style properties in Drupal or HTML's defaults.

Use CSS shorthands and style grouping

A few more ways to keep CSS short:

  • Use CSS shorthands for setting multiple properties at once. For instance, use one "margin" line to set the top, right, bottom, and left margins all at once instead of using separate "margin-top", "margin-right", "margin-bottom", and "margin-right" lines. Shorthands exist for setting margins, padding, fonts, borders, backgrounds, and more.
Long way Shorter way
div.this {
margin-top: 0;
margin-right: 10px;
margin-bottom: 1em;
margin-left: 10px;
border-top: 1px solid #CCC;
border-right: 1px solid #CCC;
border-bottom: 1px solid #CCC;
border-left: 1px solid #CCC;

}
div.this {
margin: 0 10px 1em 10px;
border: 1px solid #CCC;
}

 

  • Don't qualify classes and IDs with markup elements unless necessary. For instance, if you define a style class "this" and only use it on "div" elements, then you can safely refer to it as ".this" in the CSS file, instead of "div.this".
Long way Shorter way
div.this {
margin: 0 10px 1em 10px;
}
div.that {
margin: 10px;
}
.this {
margin: 0 10px 1em 10px;
}
.that {
margin: 10px;
}

 

  • Group shared properties. For instance, if two styles use the same margin or font, then set both styles at once instead of duplicating the CSS to set them individually. Group style properties together by listing multiple classes or IDs, separated by commas, before the opening curly brace.
Long way Shorter way
.this {
font-size: 1.1em;
font-weight: bold;
margin: 0 10px 1em 10px;
}
.that {
font-size: 1.1em;
font-weight: bold;
margin: 10px;
border-bottom: 1px solid #CCC;
}
.this, .that {
font-size: 1.1em;
font-weight: bold;
}
.this {
margin: 0 10px 1em 10px;
}
.that {

margin: 10px;
border-bottom: 1px solid #CCC;
}

 

  • Set properties broadly, then override for specific cases. For instance, don't set the same font, color, or line spacing repeatedly for every element. Instead, set the default choices for the whole page once on the "html" or "body" elements, then override them for special cases.
Long way Shorter way
h1 {
font-family: arial, sans-serif;
color: #555;

}
h2 {
font-family: arial, sans-serif;
color: #559;
}
p {
font-family: arial, sans-serif;
color: #000;
}
html, body {
font-family: arial, sans-serif;
color: #000;
}
h1 {
color: #555;
}
h2 {
color: #559;
}

 

Use the fewest images possible

Images are the worst offenders in page load times. Every background image, menu item bullet, or decorative icon takes time to download. To reduce page load times, reduce the number of images you use, and the size of those images.

For example, it is common practice in Drupal themes to use special menu item bullets for expandable menu groups. Each new kind of bullet requires another image file. Drupal's default bullet images are just 100-200 bytes each and they can be cached in your visitor's browser. However, on every page load the browser has to check in with the web server anyway to be sure that the image it has cached is still the current version. This takes time. In fact, the HTTP (Hyper Text Transfer Protocol) messages to and from the server for this check each take 500 bytes - more than double the size of the bullet image files! So, even though the image files are small and cached, they still slow down page load times.

For each image, ask yourself if it is really necessary? Do you really need custom menu item bullets, or will HTML's built-in standard bullets do? Do menu items even need bullets at all? Every image you add increases the page load time, adds more load on your web server, and forces your visitors to wait a bit longer to get a page. Minimize the use of images.

Use images that compress well

Complex detailed images don't compress well. For instance, GIF's compression scheme works great for horizontal runs of identical pixels, such as a solid background color, but its terrible for horizontal gradients or dithered dot patterns. If you design your theme to avoid such things, your background images will be much smaller and page load times will improve.

Load time results

The table below shows page load times for several variants of the "Blue Marine" theme:

  • "Blue Marine" as-is.
  • The theme, but with Drupal's three default menu bullet images disabled.
  • All of the above, but with the favorites icon and mission statement extras disabled.
  • All of the above, but with reduced CSS and HTML markup by deleting unused features: mission statement, primary links, secondary links, and RSS feed icon.

These theme changes reduce page load times another 30-50%. This is primarily from dropping the image files for menu bullets, the favorites icon, and the RSS feed icon.

Theme Simple site Complex site
Blue Marine 1.665 sec
(100%)
2.445 sec
(100%)
No bullet images 1.664 sec
(100%)
2.227 sec
(91%)
No extras 1.279 sec
(77%)
1.684 sec
(69%)
Reduced
1.152 sec
(69%)
1.294 sec
(53%)
Page load times by reducing theme complexity

Conclusions

Using a simpler theme reduces the number of CSS and image files to download, and the size of those files. A simple theme, like "Blue Marine" has half the page load time of a complex theme like "Garland." Disabling Drupal's default menu bullet images, the favorites icon, and the RSS feed icon drops page load times 30-50% more.

The simpler theme with fewer images gives page load times around 1 second, which is better than the 3-4 seconds we started with. Is there anything more that we can do? The table below lists the file sizes for the files being downloaded for the home page of our test sites:

File Simple site Complex site
Home page 3,984 bytes 5,692 bytes
Aggregated CSS 2,987 bytes 3,883 bytes
Logo image 1,767 bytes 1,767 bytes
Test.png (image in content block)   662 bytes

The CSS is about as small as we can make it, and there is only one theme image (the logo). Everything else is page content (including one content image on the complex site). To optimize even further, we'll have to look at the home page content itself.

What to do next

Some things to think about:

Further reading

Nadeau software consulting
Nadeau software consulting