Skip to main content

Jeffrey Zeldman: CSS layout revisited. Zeldman reports that Aaron Boodman has developed a Javascript workaround for IE 6's annoying habit of cutting off CSS-laid-out pages in midstream. I can't find a link to a more detailed explanation, but here is the code that Zeldman is now using on A List Apart, as found in his global Javascript file:

if (document.all && window.attachEvent) window.attachEvent("onload", fixWinIE);
function fixWinIE() {
if (document.body.scrollHeight < document.all.content.offsetHeight) {
document.all.content.style.display = 'block';
}
}

§

Jeffrey Zeldman: It's not just 4.0 browsers that make pure CSS layout a pain. Generally I agree with Zeldman on this one (having received angry letters from IE 6 users myself). Personal web development can pretty much always use pure CSS layouts these days; commercial web development, not as much.

However, I must take issue with this sentence (emphasis added):

But the combination of simple tables, sophisticated CSS for modern browsers, and basic CSS for old ones has enabled us to produce marketable work that validates -- work that is accessible in every sense of the word.

At the dual risk of either offending Zeldman or becoming a grammar nazi, I question this attempt to broaden the definition of accessibility. What purpose does this serve? Web sites that can be used by people with disabilities are accessible. Web sites that work in older browsers are not accessible; they are backward compatible. Web sites that are easy to navigate are not accessible; they are usable. Web sites that are easy for developers to program are not accessible; they are maintainable. Web sites that are a joy to read are not accessible; they are simply well-written. All of these things are important, but they are not accessibility.

Or maybe I'm just grumpy.

§

Yesterday: SSL defeated in IE and Konqueror.

Today: KDE smokes MS in SSL bug fix.

SSL, we should point out, is one of the most important consumer security protocols in use on the Web. It's what makes your credit card transactions with pr0n sites appear safe. It's what persuades you that sensitive personal data which you entrust to a Web site is a secret between you and them. Only it's broken. Mozilla isn't affected; Opera (on Windows, at least) is fixed as of today; Konqueror is vulnerable but [the patch has been checked into CVS and] will be fully patched by Monday or Tuesday, and IE is vulnerable and in Limbo while MS tries to figure out how to explain it to the teeming millions who trust their products, in preparation for eventually fixing it. But the spin comes first. That's the meaning of Trustworthy Computing.

§

Has it ever bothered you that web forms are so hard to use? For instance, in regular GUI applications, you can click anywhere on a checkbox label to check or uncheck the box, but in web-based applications, you can only click on the little checkbox square itself. This is annoying but not fatal. But for blind users, the situation is even worse. Even simple forms, like comment posting forms, can be difficult to use if you can't see them all at once. (We noted a similar problem with tables; a weblog calendar is easy to use if you can see it all at once, but difficult if you can only see it one day at a time.)

There are HTML tags which can help make forms easier to use. I'll talk about one, the <label> tag; you can read about the others in the further reading section.

The <label> tag allows you to associate a form label with any kind of form input element: text box, multi-line text area, checkbox, radio button, whatever. This allows screen readers to intelligently announce what a particular input element is, by reading the label. Furthermore, if you use a <label> tag to associate a checkbox (<input type="checkbox">) with the text next to it, your web-based form will work like a GUI application: clicking anywhere on the text label will toggle the checkbox.

Who benefits?

  1. Jackie benefits. When Jackie tabs through a form, JAWS announces the name of each element (by its name property), which may or may not be intelligible. But if the form element is associated with a label, JAWS will read the label text instead. "Text: name." (TAB) "Text: email address." (TAB) "Text: URL." (TAB) "Text area: comments." And so forth.
  2. Lillian benefits. Once form elements are associated with labels, Lillian can click anywhere on the text next to a checkbox, and it will toggle the checkbox. This gives a much wider margin of error for toggling the checkbox with a mouse, and with her limited vision, the wider the better.
  3. Bill should benefit, but he doesn't yet. He navigates mostly with the keyboard, which mostly means the TAB key. When he tabs to a checkbox in a form, Mozilla should set a focus rectangle around the entire label, but it doesn't; it just puts a focus rectangle around the checkbox itself. (Internet Explorer gets this right, though. Even Netscape 4 gets this right. Bad Mozilla.)

How to do it: Movable Type

In Movable Type, edit your Comment Listing Template. Near the bottom, you should see a form that contains elements like this:

Name:<br />
<input name="author" /><br /><br />

Email Address:<br />
<input name="email" /><br /><br />

URL:<br />
<input name="url" /><br /><br />

Comments:<br />
<textarea name="text" rows="10" cols="50"></textarea><br /><br />

<input type="checkbox" name="bakecookie" />Remember info?<br /><br />

Each of those naked labels needs to be wrapped in a <label> tag. Also, since the <label> tag points to a form element by ID (not name), each <input> tag will need an ID attribute. All in all, it will end up looking to this:

<label for="author">Name:</label><br />
<input id="author" name="author" /><br /><br />

<label for="email">Email Address:</label><br />
<input id="email" name="email" /><br /><br />

<label for="url">URL:</label><br />
<input id="url" name="url" /><br /><br />

<label for="text">Comments:</label><br />
<textarea id="text" name="text" rows="10" cols="50"></textarea><br /><br />

<input type="checkbox" id="bakecookie" name="bakecookie" /><label for="bakecookie">Remember info?</label><br /><br />

Be sure to make the same changes to your Comment Preview template, your Comment Error template, and your Individual Entry Archive.

How to do it: Greymatter

Under "Edit Karma & Comments-Related Templates", you should see a template called "{{entrycommentsform}} Posting form" that includes this:

Name
<BR>
<INPUT TYPE=TEXT NAME="newcommentauthor" SIZE=40>
<P>
E-Mail (optional)
<BR>
<INPUT TYPE=TEXT NAME="newcommentemail" SIZE=40>
<P>
Homepage (optional)
<BR>
<INPUT TYPE=TEXT NAME="newcommenthomepage" SIZE=40>
<P>
Comments
<BR>
<TEXTAREA NAME="newcommentbody" COLS=35 ROWS=10 WRAP=VIRTUAL></TEXTAREA>

Change it to this:

<label for="newcommentauthor">Name</label>
<BR>
<INPUT TYPE=TEXT id="newcommentauthor" NAME="newcommentauthor" SIZE=40>
<P>
<label for="newcommentemail">E-Mail (optional)</label>
<BR>
<INPUT TYPE=TEXT id="newcommentemail" NAME="newcommentemail" SIZE=40>
<P>
<label for="newcommenthomepage">Homepage (optional)</label>
<BR>
<INPUT TYPE=TEXT id="newcommenthomepage" NAME="newcommenthomepage" SIZE=40>
<P>
<label for="newcommentbody">Comments</label>
<BR>
<TEXTAREA id="newcommentbody" NAME="newcommentbody" COLS=35 ROWS=10 WRAP=VIRTUAL></TEXTAREA>

Further reading

§

Weblogs, with few exceptions, center around words. News, opinions, thoughts, ideas, stories, original writing: all words. Visual design is important, to be sure, but if people can't read your words, what's the point?

In the fall of 2000, Jeffrey Zeldman famously said that relative font sizing was impossible ("pixels, baby... or nothing") because of an overwhelming variety of browser bugs, starting with Netscape 4 and ending in the most modern browsers. Since then, Netscape 4 still hasn't gotten any better, and it still hasn't gone away, but at least we've all learned a thing or two about taming the browsers and making relative font sizing a reality. (Zeldman too; his recently reincarnated Web Standards Project uses the technique described below.)

Use relative font sizes in browsers that can handle them, and absolute font sizes in Netscape 4, which does not reliably support relative font sizes. You can do this even if you don't use multiple stylesheets. In a minute, I'll give copy-and-paste solutions for the default Movable Type template and all default Radio themes. And a lengthy explanation of the technique itself to help you implement it in other templates.

Who benefits?

  1. Lillian benefits. Lillian has difficulty seeing web pages clearly, due to nothing more than old age. Like 80% of the Internet population, she uses Internet Explorer for Windows, which does not support resizing text unless the web designer exclusively specifies relative font sizes. Lillian has changed the default text size in her browser (under the "View" menu, "Text Size"), but it doesn't do any good on sites that use absolute font sizes. This includes virtually every weblog template in existence. For example, this is what the default Movable Type template looks like to Lillian:

    Screenshot of Movable Type default template as seen through Lillian's eyes; text is completely blurred and impossible to read

    If the template used relative font sizes, it would look exactly the same to the majority of readers who don't need (or care) to change their text size. But this is what it would look like to Lillian:

    Screenshot of same template using relative font sizing; text is still blurred but large enough to be readable

    Again: if people can't read your words, what's the point?

How to do it: Radio

In your Home Page Template, look in your <style> section near the top for a CSS rule that looks like this:

body, td, th, p {
  font-family: verdana, sans-serif;
  font-size: 12px;
}

Keep that just the way it is, but add this immediately after it:

/*/*/a{}
body,
body td,
body th,
body p {
  font-size: x-small;
  voice-family: ""}"";
  voice-family: inherit;
  font-size: small;
}
html>body,
html>body td,
html>body th
html>body p {
  font-size: small;
}  
/* */

Make sure to include the comments at the beginning and the end. They're the key to the whole thing, as explained below.

How to do it: Movable Type

The default Movable Type template is more complex than the Radio templates, but we're going to do the same thing, just more of it. In your Stylesheet template (styles-site.css), add this at the end:

/*/*/a{}
body,
body a,
body .calendar,
body .calendarhead,
body .title,
body .sidetitle,
body .syndicate,
body .powered,
body .comments-post,
body .posted {
  font-size: xx-small;
  voice-family: ""}"";
  voice-family: inherit;
  font-size: x-small;
}
html>body,
html>body a,
html>body .calendar,
html>body .calendarhead,
html>body .title,
html>body .sidetitle,
html>body .syndicate,
html>body .powered,
html>body .comments-post,
html>body .posted {
  font-size: x-small;
}

body .date {
  font-size: x-small;
  voice-family: ""}"";
  voice-family: inherit;
  font-size: small;
}
html>body .date {
  font-size: small;
}

body  {
  font-size: 200%;
}

body .description {
  font-size: 60%;
}

body .blogbody {
  font-size: 110%;
}

body .blogbody,
body .calendar,
body .calendarhead,
body .side,
body .title,
body .sidetitle,
body .syndicate,
body .powered,
body .comments-body {
  line-height: 128%;
}
/* */

Again, make sure to include the comments at the beginning and the end.

How to do it: detailed explanation

The general idea is that we're going to use font-size keywords. These are little-used (due to bugs in older browsers), but they have three interesting properties:

  1. They don't compound. If you have a "main" section sized at 90%, and within that you have a "post" section sized as 90%, some browsers will display the post at 81% (90% x 90%), but some will display it at 90%. With more than one level of nesting (common in templates that use tables for layout), text quickly becomes unreadably small as the percentages compound. However, if your "main" section is sized as small, and the "post" section within it is sized as small, all browsers will display the "post" section as small.
  2. They resize properly in Internet Explorer for Windows. This is odd, since small sounds like an absolute size (especially in light of the fact that small nested within small is still small, see above), but it works. What can I tell you? IE/Win resizes text sized with font size keywords. I swear.
  3. They never get too small. That "Text Size" setting that Lillian uses in Internet Explorer can be used to make text smaller as well as larger. Many people with good eyesight prefer everything one, even two, sizes smaller than normal. Text sized with percentages tends to become microscopic and fuzzy when combined with the smallest default text size setting. However, text sized with font size keywords always stays at least 9px, which is readable in any font (assuming good eyesight).

So we're going to use font size keywords to specify our basic sizes. And if we need finer control than that, we're going to use percentages, but only on leaf classes that contain text (so on "post", but not "main") to avoid compounding percentages, and not too small, to avoid becoming microscopic when combined with users' smaller default text sizes.

Here's the general idea of font size keywords:

p {
  font-size: 12px;
}

/*/*/a{}
body p {
  font-size: x-small;
  voice-family: ""}"";
  voice-family: inherit;
  font-size: small;
}
html>body p {
  font-size: small;
}
/* */

There's a lot going on here, and it's all important, so pay attention.

  1. First, we're defining an absolute size (12px) for every <p>. All browsers apply this style, including Netscape 4.
  2. Then we include the odd-looking comment "/*/*/". Due to bugs in Netscape 4, everything between this comment and the following one will be ignored. That's right, all the following styles will only be applied in non-Netscape-4 browsers.
  3. Immediately after the odd-looking comment, we include an empty rule "a {}". Opera 5 for Mac is buggy and ignores this rule (and only this rule). It applies everything else.
  4. We have now carved out a realm where we can define rules that are applied in all browsers except Netscape 4. Now we can start defining relative font sizes (which Netscape 4 can't handle). The first thing we do is use a "body p" selector to redefine the behavior of the p tag. Due to the way CSS works, this will override our previous p selector. (In technical terms, "body p" is a more specific selector than "p".)
  5. We redefine the font size of all <p> tags to be x-small. This is a font size keyword which, at default settings, Internet Explorer 5 for Windows will translate into 12px. However, if the user changes their "Text Size" (under the View menu), this text will scale larger or smaller, depending on the user's setting. This is what we want. (Note: we've now defined font-size twice for IE5/Win, but that's okay, because the more specific selector always wins, and the previous selector is simply ignored.)
  6. Unfortunately, IE5/Win an off-by-1 bug with its font size keywords; every other browser in the world (IE5/Mac, Netscape 6, Mozilla, IE6/Win) will translate x-small to 10px, not 12px. Luckily for us, IE5/Win has its own parsing bug that we can exploit: it looks at that odd-looking voice-family and mistakenly thinks that this entire "body p" selector is over, so it ignores all the lines until the "}".
  7. Now we have carved out a smaller realm where we can define rules that are applied in all browsers except IE5/Win (and Netscape 4, which is still blissfully ignoring all of this). So we redefine font-size to small, which modern non-IE5/Win browsers (the only ones still listening) correctly interpret as 12px (at default settings). Again, if the user sets their "text size" to larger, this text will scale larger, which is what we want.
  8. But wait! Opera 5 has the same parsing bug that IE5/Win has, so it was also confused by the voice-family hack, but it correctly interprets font size keywords, so now our text will look too small in Opera 5. Luckily, Opera 5 supports a third type of selector, "html>body p". (Again, this is "more specific" than "body p", so it takes precedence over the previous selector.) IE5/Win does not support this type of selector, so it will just ignore it, which is what we want (since we've already compensated for it's off-by-1 bug and don't want to go mucking that up now). IE6/Win also does not support it, but that's OK, because we caught it with the "font-size: small" after the "voice-family: inherit" hack in the "body p" selector. All other browsers support "html>body" selectors, so for them we end up defining font-size four times. Again, that's not a problem, because the most specific selector always wins, and the rest are simply ignored.
  9. Finally, we have a set of empty comments: /* */. This triggers Netscape 4's parser to start listening again. If we defined any further rules after these empty comments, all browsers (including Netscape 4) would apply them.

To recap:

  1. Netscape 4 displays <p> text at 12px, regardless of user setting.
  2. Internet Explorer 5 for Windows displays <p> text at x-small, which works out to be 12px at the default setting, but would scale larger if the user set their "Text Size" setting larger in the View menu.
  3. Internet Explorer 6 for Windows displays <p> text at small, because of the "font-size: small" rule in the "body p" selector. This works out to 12px at the default setting, but would scale larger if the user set their "Text Size" setting larger.
  4. Internet Explorer 5 for Mac, Opera, Netscape 6, Mozilla, and (hopefully) all future browsers will display <p> text at small, because of the "font-size: small" rule in the "html>body p" selector. This works out to 12px at the default setting, but would scale larger if the user used the "Text Zoom" feature.

Further reading

§