AccessibilityA friend of mine was twittering about accessibility, which gave me the idea to write on how to do no-javascript friendly stylish controls such as check boxes, buttons, and radio buttons.

Because graphic designers care more about the look and site designers care more about accessibility and usability, it’s often the developers’ role to satisfy them both. So here are the tricks I use to make stylish controls look cool when JavaScript is activated, and usable when it is not.

Being mainly a PHP backend programmer, I hate to see the design cripple the code. Therefore, I always make sure that stylish and standard controls end up sending the same data to the server.

In this post, I cover buttons, check boxes and radio buttons, and provide a simple PHP helper that automatically generates the code. You might also want to check out the demo page to have an idea of what it looks like.

Buttons

Without a doubt, this is the easiest one. We usually use an A tag with an on-click or javascript: URL event to show buttons when JavaScript is enabled. The reason is: the input-image tag results in drawing tiny dashed borders upon click, and that kind of kills the nice shadow effects.

Note that I use the CSS image cropping technique, well described by the guys at UXD (or in french at Quantik Solutions).
So the typical JavaScript code for a button would be (I compacted the style sheet because it’s pretty long) :

<style type="text/css">
.button {
 border: 0; margin: 0; padding: 3px 0 0 0;
 background: transparent url(btn_bg.gif) no-repeat 0 0;
 display:block; width: 146px; height: 28px;
 overflow: hidden; font-family: Arial, Helvetica, sans-serif;
 text-decoration: none; font-weight: bold; color: black;
 outline: none; text-align: center;
}

.button:hover {
 background: transparent url(btn_bg.gif) no-repeat 0 -54px;
}

.button:active {
 background: transparent url(btn_bg.gif) no-repeat 0 -103px;
}
</style>

<h1>Button</h1>
<a class="button" href="javascript:submitForm('formName');"
    title="Send">Send</a>

The no-JavaScript code could be simpler:

<h1>Button</h1>
<input type="submit" name="submit" value="Send" />

Finally, the JavaScript/no-JavaScript condition display is done using document.write and the noscript tag.

<h1>Button</h1>
<script type="text/javascript">
document.write('<a class="button" href="javascript:submitForm(\'formName\');"
    title="Send">Send</a>');
</script>
<noscript><input type="submit" name="submit" value="Send" /></noscript>

Check boxes

This one is a little more complex, but not as much as radio buttons (which I kept for dessert). It is basically the same principle as the button, except that JavaScript required to control the checking and unchecking action when in stylish mode (while this was being done with CSS for the buttons).

First, we define a simple CSS for checked and unchecked states:

<style type="text/css">
.checked {
 background-color: black;
 width: 20px;
 display: inline-block;
 text-decoration: none;
 padding-left: 20px;
}
.unchecked {
 background-color: silver;
 width: 20px;
 display: inline-block;
 text-decoration: none;
 padding-left: 20px;
}
</style>

Then we create the check box, the stylish one first in JavaScript, and the standard one right after in a noscript tag.

<script type="text/javascript" language="javascript">
// Write the clickable A tag
document.write('<a id="checkbox1" href="#"
    onclick="toggleStylishCheckbox(\'checkbox1\', \'val\', \'checked\', \'unchecked\');"
    class="unchecked"></a>');
// Write the hidden input tag
document.write('<input type="hidden" name="checkbox1" id="checkbox1_val" value="" />');
</script>
<noscript><input type="checkbox" name="test1" value="val" /></noscript>
Check box label<br />

Finally, we need to include the control code that enables or disables the stylish check box, called by the on-click event.

<script type="text/javascript" language="javascript">
function toggleStylishCheckbox(id, value, classOn, classOff) {
  if (document.getElementById(id+"_val").value != "") {
    document.getElementById(id+"_val").value = "";
    document.getElementById(id).className = classOff;
  } else {
    document.getElementById(id+"_val").value = value;
    document.getElementById(id).className = classOn;
  }
}</script>

Radio buttons

This one is the trickiest: you need JavaScript to also to uncheck the previously checked control when checking a new one. Thus, we need to keep track of which group each radio buttons are, so we can quickly access its siblings.

The script goes pretty much as the check boxes one, but with a twist.You first need to define a checked and unchecked class for your radio buttons. You can use the same one as for check boxes.

Then we create the radio button, the stylish one first in JavaScript, and the standard one right after in a noscript tag.

<script type="text/javascript" language="javascript">
// Register the button in the group
var radioGroup_1;
if (radioGroup_1 == undefined) {
	// This is the first element, create the group
	radioGroup_1 = ["stylishRadio_1"];
} else {
	// This is not the first element, add to the group
	radioGroup_1.push("stylishRadio_1");
}

// Write the actual button code
document.write('<a id="stylishRadio_1" href="#"
    onclick="toggleStylishRadio(\'stylishRadio_1\', \'radioGroup_1\', \'1\', \'checked\', \'unchecked\');"
    class="checked"></a>');

// Create an input hidden for the group if it doesn't exist
if (!document.getElementById("radioGroup_1")) {
	document.write('<input type="hidden" name="set1" id="radioGroup_1" value="1" />');
}
</script>

<noscript>
<input type="radio" name="set1" value="1"checked="checked" />
</noscript>
Set 1, Option 1<br />

Finally, we need to include the control code that enables or disables the stylish radio buttons and their siblings, called by the on-click events.

<script type="text/javascript" language="javascript">
function toggleStylishRadio(id, groupName, value, classOn, classOff) {
  // Get the group
  var group = eval(groupName);

  // Process each radio button within it
  for (var i=0;i<group.length;i++) {
    // Get the class for this button
    var myClass;
    if (group[i] == id) {
      myClass=classOn;
    } else {
      myClass=classOff;
    }

    // Set the class
    document.getElementById(group[i]).className = myClass;
  }

  // Update the hidden input
  document.getElementById(groupName).value=value;
}
</script>

PHP helper

As you probably noticed, there is a lot of repetitive markup one need to include for every single check box or radio button. Duplication and maintenance is a pain, so why not let a PHP script do it?

Here’s the code for a PHP helper that handles the check boxes and the radios buttons automagically. This helper has been made for CodeIgniter, but can be used without it.

I wrote it as a demonstration, and there are many improvements to do. Including the JavaScript control scripts in a separate JavaScript file, for instance, and wrapping check box and radio buttons creation into a function to reduce the amount of repeated JavaScript code. Nonetheless, it works and can be useful as is for simple projects.

Also note that I did no helper for the buttons, as it is pretty simple, and the HTML markup varies a lot from project to project.

PHP Script stylishControls_helper.phps (6 KB)


If you like this article, leaving a comment, tweeting ofr liking it is always appreciated.

category CSS, HTML, Programming Friday 29 February 2008 Comment (1)

One Response :

  1. Computer Tricks

    Woohoo… This is certainly just what I have been looking for. Exactly how long did it take to make this? Thanks a bucket load for this terrific advice.

Leave a Reply