Zebra_TransForm, a tiny jQuery plugin for replacing checkboxes, radio buttons and selects

Get the latest updates on this jQuery plugin via RSS

Attempting to use CSS only to style checkboxes, drop down menus and radio buttons to have the same look and feel across browsers and operating systems it’s a lost cause: it simply cannot be done. In order to consistently style form controls cross-browser, we need a combination of CSS and JavaScript.

Zebra_TransForm is a tiny (less than 4KB minified) jQuery plugin for styling the appearance of checkboxes, radio buttons and select boxes without sacrificing functionality and accessibility. The plugin works by overlaying stylable elements over the native controls. It works in sync with the form’s original elements, preserving the tabindex, give visual feedback when focused, are accessible via keyboard, and look and behave in the same way in all major browsers.

Top

Requirements

Zebra_TransForm has no dependencies other than jQuery.

I’ve only tested with jQuery 1.5.2 but it may work in earlier versions, too. If you can test, please let me know. Thanks!

Top

How to use

First, load the latest version of jQuery either from a local source or from a CDN.

Load the Zebra_TransForm plugin

<script type="text/javascript" src="path/to/zebra_transform.js"></script>

Load the plugin’s CSS file

<link rel="stylesheet" href="path/to/zebra_transform.css" type="text/css">

Now, within the DOM-ready event do

$(document).ready(function() {

    // style all checkboxes, radio buttons and selects on the page
    var transform = new $.Zebra_TransForm();

    // unless you're planning on using the "update" method
    // you can instantiate the plugin without the "new" keyword
    // and without assigning it to a variable:
    $.Zebra_TransForm();

    // style checkboxes only
    $.Zebra_TransForm($('input[type="checkbox"]'));

    // style checkboxes and radio buttons only
    $.Zebra_TransForm($('input[type="checkbox"], input[type="radio"]'));

    // style checkboxes, radio buttons and selects (same as first example)
    $.Zebra_TransForm($('input[type="checkbox"], input[type="radio"], select'));

    // style checkboxes of a specific parent
    $.Zebra_TransForm($('#element input[type="checkbox"]'));

    // style only a specific element
    $.Zebra_TransForm($('#element'));

    // if you plan on using the plugin's "update" method
    // you must instantiate the plugin with the "new" keyword
    // and assign it to a variable
    var transform = new $.Zebra_TransForm();

    // call the plugin's "update" method
    transform.update();

});

Demo

Here are some checkboxes, radio buttons and a select box styled with Zebra_TransForm

CheckboxesFirst item is both disabled and checked

Radio buttonsFirst item is disabled

Select boxPadding also works in IE7

Top

Configuration

All parameters are optional.

style_disabled_labels boolean

If set to true, labels attached to disabled checkboxes and radio buttons will also be styled to look disabled. 

Default is TRUE

Public methods

update  

If you dynamically add or enable/disable controls, call this method to update the elements’ style. Takes as argument a jQuery object or a collection of jQuery objects as returned by jQuery’s selector engine. 

Top 

Download

version 2.1 (zip, 52.2Kb)
If you find this library to be useful to you, you can support the author by donating a small amount via PayPal:

Zebra_TransForm is distributed under the LGPL.

In plain English, this means that you have the right to view and to modify the source code of this software, but if you modify and distribute it, you are required to license your copy under a LGPL-compatible license, and to make the entire source code of your derivation available to anybody you distribute the software to.

You also have the right to use this software together with software thas has different licensing terms (including, but not limited to, commercial and closed-source software), and distribute the combined software, as long as state that your software contains portions licensed under the LGPL license, and provide information about where the LGPL licensed software can be downloaded.

If you distribute copies of this software you may not change the copyright or license of this software.


You may also like:

Top

Changelog

Click on a version to expand/collapse information.

version 2.1 (February 19, 2012)
  • fixed a bug with select boxes not being correctly replaced on Chrome
version 2.0.1 (August 07, 2011)
  • fixed a bug with the update method. thanks Michael
version 2.0 (July 19, 2011)
  • fixed a bug where the plugin was not updating in real time the selected value of a selected box, if the value was selected by pressing the ENTER key
  • fixed a bug where in IE7 horizontal padding was not taken into account for select boxes
  • fixed a bug where disabled select boxes were not styled
  • fixed a bug where select box replacements were not replicating the original select box’s font styles
  • fixed a bug where floated select boxes were incorrectly replaced
  • fixed a bug where margins of the replaced elements were not taken into account
  • fixed a bug where select boxes were not properly styled on Safari
version 1.0 (July 10, 2011)
  • initial release

Top

19 responses to “Zebra_TransForm, a tiny jQuery plugin for replacing checkboxes, radio buttons and selects”

Follow the comments via RSS
  • phil, 2011-07-25, 10:57

    Nice addon, but not really nessesary.

    Check out “http://uniformjs.com/” does the same, even supports file upload fields.

    Reply
    • Stefan Gabos, 2011-07-25, 11:08

      I know about Uniform but it doesn’t quite fit to my needs. My primary issue was that select boxes didn’t have padding in IE 6 and 7. Also, Uniform select boxes have the same width no matter what. Not to mention that I can’t alter the padding. Or the fact that the replacement doesn’t replicate the original select box’s font styles. Also, I wanted controls to be replaced no matter if they are floated, fixed, absolutely positioned, whatever margins or borders or whatever exotic CSS properties they may have applied to them.

      Anyways, it is always good to have a choice :)

    • phil, 2011-07-26, 10:17

      Ok, thats some valid points. (the selectbox width is with custom css code also possible, but if zebra does that automatically its great.)

      If you add file upload boxes i will use it :) also text boxes and buttons would be great but not really needed.

    • Stefan Gabos, 2011-07-26, 10:35

      i plan on replacing the file upload control in the next version. no plan on styling other controls though. i use this together with Zebra_Form which already does that.
      thanks!

  • Alex, 2011-07-25, 16:06

    There’s a small bug in the code. It doesn’t handle radio input with a “[" and "]” in the name – while having a radio that has a name of “field[]” isn’t likely to happen, in my case I need a few radios with the name “field[idvalue]” (where idvalue is a numeric ID.

    Anyway, there’s a quick fix. I just quickly patched my minified version to add single quotes around the jQuery selector “input:radio[name="+s.attr("name")+"]” to make it “input:radio[name='"+s.attr("name")+"']“.

    In the source code this appears on line 347. An untested replacement is:

    $('input:radio[name="' + $element.attr('name') + '"]').each(function(index, control) {

    For some reason the quotes are the other way around (single most useful in minified version, double in source version) but it should work.

    Reply
    • Stefan Gabos, 2011-07-25, 17:36

      thanks alex! i’ll have a look

    • Stefan Gabos, 2011-07-25, 18:56

      couldn’t reproduce the problem…
      i’ve tried all sorts of combinations like

      name='radio["lorem"]'
      name="radio['lorem']"
      name="radio[lorem]"
      name='radio[lorem]'
    • Alex, 2011-07-26, 08:40

      Hmm, the specific code I’m using is like this:

      HTML:

      <form>
      
          <input type="radio" name="choice[8]" id="choice-8-6" value="6">
          <label for="choice-8-6">Gold</label><br>
      
          <input type="radio" name="choice[8]" id="choice-8-7" value="7">
          <label for="choice-8-7">Chrome</label><br>
      
          <input type="radio" name="choice[9]" id="choice-9-10" value="10">
          <label for="choice-9-10">Brass</label><br>
      
          <input type="radio" name="choice[9]" id="choice-9-11" value="11">
          <label for="choice-9-11">Gold</label>
      
      </form>

      JS:

      // it's actually a little more complicated than this, but it's not the source of the bug that I can tell
      $.Zebra_TransForm($('input[type=checkbox], input[type=radio], select'));

      Maybe I didn’t make myself clear (in fact I know I didn’t). The plugin works, in that it transforms all controls, but the radios no longer act properly.

      So using the above HTML, the first two should be a radio group, allowing one option to be selected between the two, and the second two should be the same, thus the user can make two selections only in the whole snippet. But if you apply Zebra_TransForm to this (without my fix) then they all act as if they’re one group, allowing only one selection between the four radios.

      The issue, as I see it, is that your jQuery selector, when it eventually goes into the selector will turn from:

      $('input:radio[name=' + $element.attr('name') + ']').each(function(index, control) { ... });

      To:

      $('input:radio[name=choice[8]]').each(function(index, control) { ... });

      So as you can see, my “]” in “choice[8]” will end the CSS attribute selector, making the jQuery selector invalid and probably end up matching either all or none of the radios, and having the side-effect of making them all act as one grouping.

      When you apply my fix, the selector gets interpreted correctly as:

      $('input:radio[name="choice[8]"]').each(function(index, control) { ... });

      And jQuery appears to like it.

      For reference, here’s a Fiddle with the not-working version:
      http://jsfiddle.net/LHR5Q/

      And here’s one with my fix applied:
      http://jsfiddle.net/SE2pL/

      Hopefully that clarifies things a bit. (Hopefully I’ve used the code blocks better this time, too. Although I don’t know the syntax to switch between JS and HTML)

    • Stefan Gabos, 2011-07-26, 09:07

      I see now! That is some exotic approach! Can’t you just have the radios named “choice8″ the first two and “choice9″ the other two? I’ll try and make it work for these kinds of situations. I’ll keep you updated.

  • Alex, 2011-07-28, 15:03

    Thanks.

    Yeah I could do that, but the proper way to do it (I’d say) is the way I’ve done it. These numbers in “choice[8]” and “choice[9]” refer to ids in a database that someone’s choosing something about. (Specifically the finishes they want on a certain thing, e.g. kitchen cupboard door handles, hence gold, chrome etc. in my example)

    As I said, the fix is really simple (and it works, I tested it and indeed am using it), just change line 347 so that the jQuery selector has quotes around the dynamic attr(‘name’) that you’re putting in.

    Otherwise, great plugin by the way. Works great and like you said above, it appears to work in many situations (floated, positioned, etc.) which is great for me as my pages are as complex as my choice of input names!

    A patch (created with `diff -u old.js new.js > fix.patch`, no idea if that’s the correct way to do it for actual patch applying) is uploaded at http://clevercherry.com/zebra/fix.patch if you wanted a patch.

    Reply
  • Alex, 2011-08-01, 19:01

    Is there any way to update the already existing ZTs? I have a form that needs to show/hide a section based on something else, and as I hide the section its transformed floating checkboxes stay on the page.

    I’ve tried using the update method and passing in the original selector but it doesn’t appear to work.

    At the very worst is there an undo/detach thing so I can just re-add ZT?

    Reply
    • Alex, 2011-08-01, 19:10

      Ahh, found a quick bodge around it – set the container of all ZT inputs you have to position: relative. It’s not idea but is (so far) a viable solution for me. Still, it’d be nice to have a “recalculatePositioningAndWhatNot” function on ZT.

    • Stefan Gabos, 2011-08-01, 19:25

      sounds like a bug. i’ll have a look. thanks!

  • Michael, 2011-08-04, 23:26

    In your Javascript demo code you have:

    transform->update();

    You must have been in PHP mode still as was I. Should be:

    transform.update();

    I end up getting “h.destroy is not a function”.

    Reply
    • Michael, 2011-08-04, 23:35

      I’m new to jQuery (Mootools user…), but I changed the reference from destroy to remove. That appears to make it work correctly. Now when I call transform.update(), the select boxes resize.

    • Stefan Gabos, 2011-08-06, 19:35

      thanks! both are fixed now

    • Alex, 2011-08-09, 09:22

      A-ha, this may have been what was breaking for me above in my comment that says “I’ve tried using the update method and passing in the original selector but it doesn’t appear to work.” I just figured the “h.destroy is not a function” was something I did wrong.

      Oh well the bodge I found kinda works anyway.

  • zvzz, 2011-09-06, 18:09

    Hoi Stefan
    There are some performance issues when there are many of them controls on the page. In my case, 15 rows with 5 checkboxes on each would freeze up my PC for a few seconds every time the data grid opens with some fresh data – unacceptable for me, had to switch it off, but I loved your thing anyway. Thanks for the efforts !
    Alexey

    Reply
    • Stefan Gabos, 2011-09-11, 21:08

      thanks! I’ll see what I can do about that

Leave a Reply

Your email address will not be published
You can use <strong>, <em>, <a>, <img>, <code>
Characters are not case-sensitive