All in the <head> – Ponderings and code by Drew McLellan –

Coping With Internet Explorer's Mishandling of Buttons

One of the more exasperating quirks of Internet Explorer is the way it mishandles BUTTON elements. If you’re not all that familiar with HTML buttons (and don’t be ashamed, it’s not all that widely used) it’s a very useful element. Unlike regular the INPUT with its type set to submit which displays its value as a textual label on the UI element, a BUTTON can have both a value and contain a mixture of text, images and what have you.

Let’s look at an example:

Delete message

When a user activates the button, the form would be submitted containing an item named “delete” with a value of “1234”. On the server side, you can then pick up that a delete button has been activated, and from the value you know which item you should be deleting. All the while, the user interface displays an attractive button with an icon and some call-to-action text.

The problem with IE

I don’t claim to know anything about the internals of a browser, but I sort of understand how CSS bugs occur. The spec is open to interpretation in places, and generally laying stuff out is a hard problem. There are lots of factors to consider. Sometimes even writing CSS for a given layout can be hard, so it’s a bit mind-blowing to think how difficult a job it is to translate that into graphical elements in a window. Bugs happen, but really I’m surprised all works so well at all.

When it comes to something like a form element, things are more clear-cut. Most elements have a value attribute, and it’s the contents of that attribute that get sent to the server. That’s the same for text fields, checkboxes, submit buttons – the only one that stands out as different is textareas. If you read the spec for the BUTTON element, the description for the value attribute even says:

value CDATA #IMPLIED — sent to server when submitted —

Seems pretty clear. However, what IE does is send the innerHTML value of the button. Just like if it were a textarea, really. The content of the value attribute is discarded entirely. The result from the above example, remembering that IE handles HTML all in uppercase, would be something like:

delete= Delete message

From my testing with the current beta of IE8, it looks like this bug has been fixed. Thank goodness. But how can we deal with the problem today for IE6 and 7 users?

Working around the issue

I encountered this problem last night on an e-commerce project. Each item in the cart had a “Remove item” button, that although styled as a link, needed to be a button as its activation makes a change to the user’s cart. As my cart display was wrapped in one big form (each item had a quantity field) I was using a BUTTON element with its value set to the product code in order to detect which item to remove.

Remove item

In Firefox, this would being submitted as remove=ABC123, which was enabling me to both detect that a removal button had been activated (by the presence of the remove item in POST) and the product code of the item to remove form the cart (using the value). In Internet Explorer, the same action resulted in

remove=Remove item

As no product in the cart had a product code of “Remove item” the action was failing. My work-around to the issue is not elegant but did enable me to get the show back on the road. I amended my HTML to include the value inside the button, and wrapped the product code inside a SPAN:

Remove item ABC123

Borrowing from a common accessibility technique, I then threw the SPAN off-screen with CSS, resulting in no visible change to the button. Without CSS or for non-visual users, the text used for the button is still acceptable for my purposes. This meant that when posted, the field came through as:

remove=Remove item ABC123

All I needed to do was to add a quick test in my form handler to look for the presence of the string in the value, and if present, perform a quick string manipulation to extract the product code.

Not pretty, but also not harmful, and it worked.

Addendum

My friend and former colleague David Dorward dropped me a note to explain that things get even more complex with IE6. Apparently that browser will send all buttons in the POST, regardless of whether they’ve been activated. In my case, that could mean all items being removed from the cart, which would be bad.

So if you’re still building for IE6, it may be back to the drawing board. Thanks David!