Border Around IE6, 7, 8 Form Submit Button

IEs have an interesting behavior around forms that may drive pixel-perfect designers and implementers nuts.  In certain conditions, IE6, 7 and 8 will “enhance” the form functionality by showing you which button is the submit button by drawing a black, 1 px border around it.

If you’re like most web-devs, you style inputs, textareas, and especially buttons to match the look-and-feel of the overall site.  Usually that entails setting properties like background-image and border.

The issue can be reproduced when the following criteria is fulfilled:

  1. use a form in your site
  2. use the standard <input type=”submit” /> button to trigger form submission
    • OR use the <button type=”submit”> to trigger form submission
  3. style the button visually using CSS

My test page can be downloaded here: test page

In this image, we see a standard form in IE7 with one text input field and one submit button.  Both the inputs are styled with a 1px solid #ccc border and #eee background-color.  Pardon the horrible render; MS Paint doesn’t have a lot of options for export.

formOff

In this image we see the same form in IE7 with focus (by clicking into the text input field).

formOn

It’s a subtle change, and most won’t notice it.  It only becomes an issue if your UI/UE team gets really antsy about visual changes that they didn’t want.

Two simple fixes come immediately to mind.

  1. Change the <input type=”submit” /> or <button> to a simple button and trigger the submit with javascript.
  2. Implement a CSS fix that tricks IE into not displaying the border.

For solution 2, the fix is a pretty straightforward one with some caveats.  Add this bit of CSS to whatever style cascades down to the submit button:

.fixIE {
filter : chroma(color=#000000);

}

“Filter” is IE-specific.  “Chroma” will set to transparent whichever color is cited, so in the above case, if an element has or inherits the “fixIE” class, anything with the color #000000 (or black) will be set to transparent.

The caveats should be obvious.  Not only will the extra border be transparent, but if the default text color or background-color is #000, it will be rendered transparent.

There’s a slightly less-obvious caveat as well to this.  Even as the color itself is rendered transparent, IE will still draw the border around the button.  The net effect is that as the form receives focus, the submit button will act as if  a 1px margin was applied around the element, and it will visually contract.  It will expand back out to the previous size if focus moves to some other element in the page not contained by the form.

Pretty ugly hack, and I’m inclined to tell you to just use fix 1.

Javascript toSource() in IE6/7

Mozilla based browsers have a pretty nifty instance method “toSource()”. It simply outputs a string literal representation of any Javascript object, which is at heart, *anything* in the Javascript interpreter.

The main reason I use this method is to do a quick & dirty deep copy of Javascript objects and arrays. When paired with the “eval()” function, you can be 100% sure that the new array or object you just created is its own instance and doesn’t have reference pointers to existent objects or arrays.

My main use-case is using an object as hashmap or associative array, but needing to copy it regardless of whether one of its member attributes is another object or array (which would preserve the pointer). Performing a toSource() and eval() allow you to do just this.

var burdensomeBabyNames = [ ... ]; // imagine a deep array of strings, other arrays, objects, etc.
// now we have a deep copy, quick and easy|dirty
var burdensomeBabyNamesCopy = eval(burdensomeBabyNames.toSource());

For example, say you have an array of names in memory: “Oedipus”, “Ophelia”, “Freya”, “Loki”, “Lachesis”, “Atropos”, and “Morta”.

If that array was instantiated in memory as “burdensomeBabyNames”, the string literal representation would look something like:

var burdensomeBabyNames = [
  'Oedipus', 'Ophelia', 'Freya', 'Loki',
  'Lachesis', 'Atropos', 'Morta'
];

In a Mozilla based browser, one could call “toSource()” return an useful textual representation of the string literal. I.e., calling:

var xNames = burdensomeBabyNames.toSource();

The var xNames would now contain the string:

['Oedipus','Ophelia','Freya','Loki','Lachesis','Atropos','Morta']

Great, huh? That’s really useful if you never have to consider the Internet Explorer crowd, but since IE still owns a ridiculously high percentage of the browser usage pie, folks who use this functionality need a work-around.

Anyone who’s worked with asynchronous calls vis-a-vis JSON (Javascript Object Notation, see http://www.json.org) will see that the toSource() call is just a rough draft of the much deeper JSON.encode().

The same example as above could be rewritten to use JSON encode and decode:

var burdensomeBabyNames = [ ... ]; // imagine a deep array of strings, other arrays, objects, etc.

// serialize or "toSource()" the array
var burdensomeBabyNamesJSON = JSON.encode(burdensomeBabyNames);

// now we have a deep copy, quick and easy|dirty
var burdensomeBabyNamesCopy = JSON.decode(burdensomeBabyNamesJSON);

One could just include the minified version of JSON.js from the above link and call it good. If you happen to be working within a framework like YUI (Yahoo UI, see http://developer.yahoo.com/yui) or ExtJs (see http://www.extjs.com), the encode/decode functionality is already folded into the core library.

IE6 Javascript Form Submission – Hit or Miss

Internet Explorer 6, a venerable old browser to be sure, is still widely used despite the availability of much better (and free) alternatives. This continues to be a time-sink for any front-end developer.

While not at all a technical observation, my one reproducable use-case around this bug was by:

  1. Programatically creating a DOM Element <div>
  2. Dynamically creating and assigning an onclick event handler to the <div>
  3. Trying to submit a given form with validation and some custom hidden <input> fields.

What I observed is that the click propagation doesn’t seem to want to return from the onclick handler function

Here’s a fun one:

document.getElementById("myFormId").submit();

Should be straightforward, correct? In some select cases, this actually will not work.

The workaround:
Set the scope to the document level and force submission with a short timeout.

document.doSubmit = function() {
    document.getElementById("myFormId").submit();
}
setTimeout("document.doSubmit();", 50);

Putting it all together:
Here’s your trigger, say an <img> tag:
<img src="..." onclick="submitMyForm();" />

Here’s the form submit function:

function submitMyForm() {
    // do some validation, completion checking, etc.
    ...
    // now call the externalized submit function
    document.doSubmit();
}

Here’s the setTimeout handler:

document.doSubmit = function() {
    document.getElementById("myFormId").submit();
}

The <img> tag’s onclick event calls submitMyForm() which then calls document.doSubmit() .