Pre-Compressing Web Content

This was definitely a “D’oh!” type of problem.

One thing I’d been meaning to figure out for a while was how to send gzip-compressed files to a browser. That is, if I have a large HTML file, it’d be nice if the server could compress it to save bandwith and transmission time. Yes, Apache has mod_deflate which takes foo.html and gzips it on the fly, setting all the appropriate HTTP headers. But for static content, I should just be able to compress the file in advance. If the browser asked for foo.html, I wanted Apache to see that there’s a foo.html.gz and send that instead, with headers saying that it’s a text/html file that happens to be compressed.

mod_mime seemed like just the thing: just add

AddEncoding x-gzip .gz

to .htaccess. But every time I did that, Apache sent back “Content-Type: application/x-gzip“, so my browser treated it as a random file of unknown type that happened to be compressed.

Then I noticed that my vanilla-ish site-wide Apache config had

AddType application/x-gzip .gz .tgz

so that when Apache saw foo.html.gz, it ignored the .html extension, and saw only the .gz one.

The fix was to add RemoveType to my .htaccess:

RemoveType .gz
AddEncoding x-gzip .gz

And voilĂ ! .gz stops being a file type and becomes an encoding, allowing .html to shine through.

I’ll add that this plays nice with AddLanguage as well. In my test setup, I have foo.html.en.gz, for which Apache returns the headers

Content-Type: text/html
Content-Encoding: x-gzip
Content-Language: en

I.e., it’s an HTML file, it’s gzip-encoded, and it’s in English.

Just as importantly, this works with other file types (e.g., CSS files and JavaScript scripts), and XMLHttpRequest does the Right Thing with them on all of the browsers I care about.

A Better Way to Toggle

(Warning: what follows may be obvious or trivial to many.)

One of the cool things about AJAX is switching parts on and off: you
can make an element visible simply by

myElement.style.display = "block";

or hide it with

myElement.style.display = "none";

But the problem with this is that it requires the JavaScript script to
know a lot about the document. The example above doesn’t look too bad,
but what if you have something like a pulldown menu that appears when
you click a button?

Let’s say that originally, the button is gray and has a “+” icon next
to the text. When you click on it, the menu becomes visible, but the
button also changes to red, and the “+” icon changes to “-“, to show
that the menu is active.

Now you have all sorts of CSS resources that you have to keep track
of. It would be nice to put them in the .css file, with the
rest of the style stuff.

Read More

Different Stylesheets for Browsers With and Without JavaScript

As hacks go, this one is pretty obvious, but I thought I’d throw it
out there anyway.

Let’s say there are three stylesheets you want to use on your web
page: one for all browsers (style.css), one for browsers with
JavaScript enabled (style-js.css), one for browsers without
JavaScript (style-nojs.css). This can be useful for things
like “display the fancy drop-down menu only if the browser supports
JavaScript; display the plain-HTML menu only if the browser doesn’t
support JavaScript”.

The common stylesheet is pretty standard:

<link rel="stylesheet" type="text/css" href="style.css"/>

The one for browsers that don’t support JavaScript is also pretty
easy: that’s what <noscript> is for:

<noscript>
  <link rel="stylesheet" type="text/css" href="style-nojs.css"/>
</noscript>

Finally, what’s the best way to have different behavior in browsers
that support JavaScript? Why, run a script, of course:


  document.write('n');