An IE Pitfall With Class Name Alteration

I recently used the basic principles in Validation Hints For Your Form by askthecssguy.com for a password management application. I didn't notice any problems on my speedy development machine, but when I pushed the app to some beta testers, I noticed some slower-than-expected performance in IE. As it turns out, the problem was due to the JavaScript that would update an element's class, triggered by the onkeyup event of an input field. It was slow enough to even be disruptive to the experience.

Here is an example of a function that could duplicate the slowdown in IE. It could be attached to the onkeyup event of the username field. It will provide immediate feedback by altering the class name of the field's container when criteria are met (in this case, the value being greater than 7 characters in length). Your CSS and HTML can then determine exactly what that feedback will look like.

function checkUsername(whatYouTyped)
{
  var fieldset = whatYouTyped.parentNode;
  var txt = whatYouTyped.value;
  if (txt.length> 7) fieldset.className = "welldone";
  else fieldset.className = "";
}

As it turns out, the slowdown in IE is due to a general slowdown that IE experiences anytime the class name of the element is changed. It may be unnoticeable if it happens once, but when it happens on every key press, it is noticeable. The slowdown only occurs, however, when the class name is changed, not when the value is referenced. So the easy solution is to compare the existing value to the value you want to set, and only assign the class name if it is different.

You might change the function above to look something like this.

function checkUsername(whatYouTyped)
{
  var fieldset = whatYouTyped.parentNode;
  var txt = whatYouTyped.value;
  var newClassName = "";
  if (txt.length> 7) newClassName = "welldone";
  if( fieldset.className != newClassName )
    fieldset.className = newClassName;
}

This will theoretically improve performance in all browsers, although it is relatively moot in Firefox, as it doesn't experience the same level of slowdown. But for IE, this tweak in your code will make a noticeable speed improvement.

Floating Form Labels

I seem to always forget this, so hopefully blogging about it will help me remember and serve as a future reference.

We're using labels to line up form elements like so:



No problem. Everything looks great. Now I'll take that same concept but add some disparity in the heights of the label and the content. For this example, let's use a <div> with multiline content. Let's put borders around the content areas so that we can see what's going on.

Here is the HTML:

<div class="row">
    <label>Date/Time:</label>
    <div>5/21/07, 11:14:34am.</div>
</div>
<div class="row">
    <label>Message:</label>
    <div>
        This is a message.<br />
        What a very nice message indeed.<br />
        I love messages.
    </div>
</div>

Some CSS like this might work:

label {border: 1px dashed maroon; width: 95px; float: left; text-align: right; font-weight: Bold;}
div.row {margin-bottom: 7px;}
div.row div {border: 1px dashed green; }

That should produce something like this:

5/21/07, 11:14:34am.

This is a message.
What a very nice message indeed.
I love messages.

Oh my. That's not the effect I was shooting for. But look at the green borders of the inner divs. They aren't next to the floated label like I'd expect; they are on top of it, but their content still flows around the floated label, which is why the first example above with the text fields looks fine, but this multiline div reveals the actual behavior the div has when it sits below a floating element.

Right around now is when I'm cursing floats and dreaming of the days of table-based layouts. ;-) This behavior is actually intentional though, and once you understand it, it isn't hard to work with. Like the Float Basics page on Floatutorial points out:

A floated box is laid out according to the normal flow, then taken out of the flow and shifted to the left or right as far as possible. Content can flow down the right side of a left-floated box and down the left side of a right-floated box.

That explanation makes the behavior make perfect sense. The label is taken out of the flow, and thus the <div> sits on top of it. Once you understand that, it is easy to see that a left margin or padding will take care of the div's alignment.

This change:

div.row div {margin-left: 105px; border: 1px dashed green;}

Produces the desired effect:

5/21/07, 11:14:34am.

This is a message.
What a very nice message indeed.
I love messages.

The final result, without the borders:

5/21/07, 11:14:34am.

This is a message.
What a very nice message indeed.
I love messages.

A Better Way to Handle CSS Issues in IE

All web developers are familiar with the need to tweak their CSS so that it will look presentable in both IE and other more standards-compliant browsers. Many people have declared, some more infamously than others, that people should boycott IE, and have proceeded to develop designs that are standards-compliant but IE-unfriendly. I feel that this is foolish; IE is still the browser of choice by most non-geek web surfers, and unless you're developing in a controlled environment where you can declare the browser to be used, you really should code for any popular browser, and even then, it's just good practice to write clean code that works everywhere.

Alas, I digress. The point is that IE isn't going anywhere for now, and it is a pain sometimes to figure out how to write CSS that renders as close to identical as possible between IE and other browsers like Firefox. There are several sites out there that endeavor to explain the IE bugs and, when possible, provide workarounds.

Sure, I could just alter the CSS to look right in IE, but if I'm not careful, that "fix" then breaks the code in Firefox! So we've come up with hacks to have CSS that other browsers will see but IE ignores. I don't know about you, but I'm tired of trying to understand and remember these tricks for satiating IE.

Welcome to conditional comments in IE. This is yet another IE-specific feature that we can actually use to our advantage to level the playing field.

Conditional comments are just what they sound like: HTML comments. But these comments are coded in such a way that effectively have a conditional statement in them, and any HTML output within the comments will only be included (by IE) if the condition is true. Here is an example.

<!--[if IE 6]>
    <p>I'm running IE 6.</p>
<![endif]-->

As you can see, any non-IE browser will just ignore all the content, since it's really one large comment. But IE recognizes the conditional logic inside the comment and renders the content accordingly.

Here's an example. This box will have a message if you're on IE, and it will be blank if you're in any other browser:

If you wanted, you could use this technique to inject HTML elements specifically for IE.

Yeah. If you want a maintenance nightmare. Do not sprinkle conditional comments in your code.

Rather than having a CSS file littered with IE fixes (or just accepting the variances between IE and Firefox), I would much rather have a single "clean" stylesheet file that is then augmented by an IE-only stylesheet, loaded by IE and ignored by all other browsers via the conditional comments feature.

So, perhaps you might have some code like this in your header:

<link rel="stylesheet" href="site.css" />
<!--[if IE]><link rel="stylesheet" href="ie.css" /><![endif]-->

There is still a very real danger here. You don't want to fall into the tendency to write intolerant CSS that needs a lot of "cleanup" to look good in both browsers. Work hard to make your CSS as compatible as possible, and leave the ie.css file exclusively for the rare cases where you could not resolve an inconsistency in IE. When you're done, your ie.css file should be really small, if you require it at all.

Having said that, however, I think this is a graceful solution. You don't sacrifice the consistency of your HTML nor your CSS, and your only extra work is the tweaking done in your IE stylesheet. Other solutions like Targeting IE Using Conditional Comments and Just One Stylesheet over at PositionIsEverything.net recommend adding an IE-specific div tag around your content, which would enable you to have a single stylesheet and to not just include IE-specific styles but also exclude certain styles from IE. Unless you have some CSS that you just can't tweak for IE and you have to exclude it, I definitely prefer the simpler approach of just including a secondary, corrective stylesheet and leaving the HTML alone. But that's just the purist in me.

Scriptaculous Cheat Sheet

If you're not using Scriptaculous yet, start using it!

And once you do, you can reference this awesome Scriptaculous Cheat Sheet designed by Amy Hoy of Slash7.  She did a great job at covering the basics, keeping it simple.

  Theme Brought to you by Directory Journal and Elegant Directory.