Better Check Boxes with jQuery and CSS
In this short tutorial, we will be creating a replacement for the default browser checkboxes in the form of a simple jQuery plugin. It will progressively enhance your forms but at the same time fall back to the default controls if JavaScript is unavailable.
HTML
The first step is to lay down the structure of the underlying HTML document. We will need a form with checkboxes which we will later be replacing with their enhanced jQuery versions.
index.html
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Better Check Boxes with jQuery and CSS | Tutorialzine Demo</title> <link rel="stylesheet" type="text/css" href="css/styles.css" /> <link rel="stylesheet" type="text/css" href="jquery.tzCheckbox/jquery.tzCheckbox.css" /> </head> <body> <div id="page"> <form method="get" action="./"> <ul> <li> <label for="ch_effects">Display effects: </label> <input type="checkbox" id="ch_effects" name="ch_effects" data-on="Show effects" data-off="Hide effects" /> </li> <li> <label for="ch_location">Enable location tracking: </label> <input type="checkbox" id="ch_location" name="ch_location" checked /> </li> <li> <label for="ch_showsearch">Include me in search results: </label> <input type="checkbox" id="ch_showsearch" name="ch_showsearch" /> </li> <li> <label for="ch_emails">Email notifications: </label> <input type="checkbox" id="ch_emails" name="ch_emails" data-on="ON" data-off="OFF" /> </li> </ul> </form> </div> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script> <script src="jquery.tzCheckbox/jquery.tzCheckbox.js"></script> <script src="js/script.js"></script> </body> </html>
The main container element - the #page
div, holds our form. Inside it is an unordered list with a number of label
elements which describe the checkboxes. Something that is good from a usability standpoint, is that clicking a label will check/uncheck the corresponding checkbox (specified by the for attribute).
Notice the HTML5 data
attributes, specified on some of the labels. We are using these to attach custom data to every tag in an HTML5 document. In our case the attributes will determine the text labels of the on / off states of the checkbox replacements.
And here is the markup of our replacement checkboxes:
<span class="tzCheckBox checked"> <span class="tzCBContent">ON</span> <span class="tzCBPart"></span> </span>
When our plugin is called, it will loop through the checkboxes, and insert the HTML code you can see above after each one, while at the same time hiding the original. The checked
class determines the styling of the checkbox replacement (on or off state).
Now lets move on to the styling.
CSS
We are using a single transparent PNG background image to style the checkbox replacements. The top part of the image is the checked (on) state and the bottom - the off state. The width of the checkbox replacement grows with the text labels.
jquery.tzCheckbox.css
.tzCheckBox{ background:url('background.png') no-repeat right bottom; display:inline-block; min-width:60px; height:33px; white-space:nowrap; position:relative; cursor:pointer; margin-left:14px; } .tzCheckBox.checked{ background-position:top left; margin:0 14px 0 0; } .tzCheckBox .tzCBContent{ color: white; line-height: 31px; padding-right: 38px; text-align: right; } .tzCheckBox.checked .tzCBContent{ text-align:left; padding:0 0 0 38px; } .tzCBPart{ background:url('background.png') no-repeat left bottom; width:14px; position:absolute; top:0; left:-14px; height:33px; overflow: hidden; } .tzCheckBox.checked .tzCBPart{ background-position:top right; left:auto; right:-14px; }
The .tzCheckBox span is positioned as an inline-block, which keeps it on the same line as the surrounding text, while giving us the ability to style its margin and padding properties as a block element. It also has a relative positioning assigned, so we can use the sliding doors technique and show the .tzCBPart
span with the remaining part of the background.
Depending on whether we are displaying the on or off state, the .tzCPContent
span is either aligned to the left or the right, with the appropriate paddings so that it makes its .tzCheckBox container span grow.
Now it is time to build the actual jQuery plugin.
jQuery
We are going to name our plugin tzCHeckbox
. It is going to take a JavaScript object, with a labels
property as a parameter. This property is an array specifying the text labels displayed in the on / off state.
jquery.tzCheckbox.js
(function($){ $.fn.tzCheckbox = function(options){ // Default On / Off labels: options = $.extend({ labels : ['ON','OFF'] },options); return this.each(function(){ var originalCheckBox = $(this), labels = []; // Checking for the data-on / data-off HTML5 data attributes: if(originalCheckBox.data('on')){ labels[0] = originalCheckBox.data('on'); labels[1] = originalCheckBox.data('off'); } else labels = options.labels; // Creating the new checkbox markup: var checkBox = $('<span>',{ className : 'tzCheckBox '+(this.checked?'checked':''), html: '<span class="tzCBContent">'+labels[this.checked?0:1]+ '</span><span class="tzCBPart"></span>' }); // Inserting the new checkbox, and hiding the original: checkBox.insertAfter(originalCheckBox.hide()); checkBox.click(function(){ checkBox.toggleClass('checked'); var isChecked = checkBox.hasClass('checked'); // Synchronizing the original checkbox: originalCheckBox.attr('checked',isChecked); checkBox.find('.tzCBContent').html(labels[isChecked?0:1]); }); // Listening for changes on the original and affecting the new one: originalCheckBox.bind('change',function(){ checkBox.click(); }); }); }; })(jQuery);
All changes to the checkbox replacement are propagated back to the original checkbox (which is hidden, but still on the page). This also works the other way around, as in certain circumstances (when you click on a label
element for example) the original checkbox might be changed. This will trigger the change event and update the replacement.
Keeping the original checkboxes on the page is important, as this way submitting the form (with or without AJAX) would also send the correct values the user has chosen.
Using the plugin is also pretty straightforward:
$('input[type=checkbox]').tzCheckbox({ labels: [ 'Enable', 'Disable' ] });
This selects all the checkboxes on the page and passes them to tzCheckbox
with 'Enable' and 'Disable' as replacement text.
With this our checkbox replacement jQuery plugin is complete!
Conclusion
You can use today's plugin to enhance the admin or configuration panels of your web apps, or even built better mobile sites with it. If, for some reason, JavaScript has been disabled on the user's browser, they will still see the default checkboxes as a fallback.
Bootstrap Studio
The revolutionary web design tool for creating responsive websites and apps.
Learn more
Nice tutorial. Well done! Really usefull.
Regards,
Alex
Very nice! Since the control invites to "slide" the button to the other side, I would add the option to change the value when the button is dragged http://threedubmedia.com/code/event/drag
Really cool stuff.
I just test with latest, ie, opera, safari, chrome and FF and works perfect
was wondering about ie8, ie7
not so much about ie6
It works everywhere (haven't tested it on IE6).
However there is a problem with IE in that it does not support the "change" event on checkboxes when they are hidden, so clicking the labels would not work.
It reminds me of how I created the iOS styled on/off buttons. Great job! Very useful!
Very nice, but in the demo if you click to the left of the actual button it works the same as clicking the actual button. Might want to check that out. =-)
I'm pretty sure thats a feature caused by the tag.
that's default html label element functionality :)
I looked at the code in Firebug, and it appears that the label click is also triggering the change, which is the normal functionality of a button.
**I meant of a checkbox
Ohhh, very nice!!!
Would be good if there was a left-to-right & right-to-left slide effect when clicked...otherwise awesome work.
This is similar to a design I worked on recently. Having it wrapped up in a jQuery plugin is handy. Having the switch animate would be a nice addition - here's an example of what I did: http://preation.blackantmedia.com/switches.html
It looks really impressive Jason! The only suggestion I have is to add an outline:none property as it currently shows in Firefox.
I disagree with this. The dots are there for a good reason: keyboard navigation.
Love your implementation and I suggest you add outline: none; to your a on the button css to remove the dots in firefox!
Sorry I didn't read your reply before I posted mine Martin!
Tim it's a part of the plugin ...
"All changes to the checkbox replacement are propagated back to the original checkbox (which is hidden, but still on the page). This also works the other way around, as in certain circumstances (when you click on a label element for example) the original checkbox might be changed. This will trigger the change event and update the replacement."
Hoping for 'Better radio buttons [...]' next week!
Great article. It came just as I was working on an admin panel and was try to figure out how to style the options. You definitely pointed me in the right direction.
Woah , I Love it! :)
Nice job...Thanks for sharing..will help a lot.
Regards,
Sri
Again Awesome Work! Thanks for sharing!
Thank you for the awesome comments, folks!
I used this type of check box replacement a little while back but people couldn't understand if it was checked or not. The changing labels confused them. Is it on when it says on? Or is it off when it says on and it's telling me that if i click on it will be now be on but say off?
Even though people use switches just like this in real life. The usage still escaped them. So in the long run, while I love these, it fails as far as usability goes.
not that it would be hard to make it absolutely clear.
You beat me to it; a better description of the current state is required. In particular I thought the labels and colours sent confusing signals. Perhaps if I were red/green colourblind ...
Having the descriptions to the side, phrased in such a way that you can stick with on/off or enabled/disabled in all cases would be clearer.
But the appearance is certainly attractive.
I can see how it could be confusing, but if used in the right context I think it could be okay. Such as making sure the labels are understandable to the on/off. Ex: Lights - On/Off is okay, whereas Lights Off - On/Off might get confusing.
Great technique Martin
but It can be spiced up by using CSS3 transitions property with just a line of CSS code, e.g. "-webkit-transitions:all linear 1s;" (but in that case sprite images should be placed side by side not top to bottom)
Martin,
Truly amazing again. What a great eye for code! I would never of thought to do check boxes like this.
PS. Take a look at this site for me, give me your feedback, need some fresh eyes on it: http://www.arnott-conveyors.co.uk/testing/index.html
Speak soon mate
pretty cool effects ;) thanks for sharing the code .
Really nice example and I guess a little animation won't hurt. I kind of prefer the click over the drag because of mobile functionality. So far, I haven't seen any site or plugin that makes use of the drag while browsing on a mobile device.
Very lovely and creative!
Really nice tutorial. Thanx ;]
Just a little suggestion for funzies... I think it's clearer to label either side of the control, like this: http://cl.ly/5RNJ
As it stands, there is a little confusion as to what the label inside the control means. It could mean:
1) This control is currently at the value shown
2) If I click it, the control will THEN be at the value shown
Just thought you might be interested in this. http://codecanyon.net/item/html5-slick-slider-checkboxes/180044
Seems as though someone is trying to profit of what you have provided here. Nice tutorial by the way, thanks!
The codes are really amazing. I would never of thought or seen to do check boxes like this. great tutorial.
To be clear, I am able to pass either a 1 or a null value with the checkbox, however, I can't make the check box show OFF if there is a NULL value in the database.
yes, I have resolved this matter :]
thanks for your awesome script. works a treat.
in jquery 1.6.2 has bug
I change it
now good work in jquery 1.5.2 /1.6.2
Where do you edit this? I can't find the replacement..?? :S
Thanks a lot buddy...U saved my day. Thanks a ton
very nice! but i have a question. i don´t want to use labels and i use jquery functions to manage the option.
so when i click on button, jquery doesn´t execute the command. can u help me?
jquery:
$('#habilitar-base').click(function() { $('#senha-base').attr('disabled', false); });
html:
on
thanks in advance and congratulations for this tutorial =)
Seems to fail when i use another jquery object within the same page
http://www.erichynds.com/jquery/jquery-ui-multiselect-widget/
and i find if i delete the line
the script works again :(
not sure if i can have 2 differnt jquery scripts riding on the same page
with Jquery 1.7.1:
(in jquery.tzCheckbox.js, find "// Creating the new checkbox markup:")
Awesome, thanks for the fix and thank you Martin for sharing.
The plug in background image disappears when I use JQuery 1.7.1. Any one know of a fix for this?
Made a change to the jquery.tzCheckbox.js file
I wanted the original class from the old checkbox to set on the new button so I can handle multiple buttons on a page.
http://pastebin.com/gsAeQMpx
I have modified a JS for include 2 new function: javascript caller and enabled state..
http://jsfiddle.net/ULphC/
I have custom select all/none buttons. However when they are clicked tzCheckboxes are not changed accordingly. Is it because the way I did it does not fire change events?
If u got any solution then do mail me d solution...required it very badly.
[email protected]
Work more than good
But I have problems not to display the value when you use this code
$ ('input [type = checkbox]'). tzCheckbox ({labels: ['Enable', 'Disable']});
Thanks
This is a great plugin - exactly what I was looking for. I'm having two difficulties, though. First - I can't seem to get the checkbox to return a value. Even when I click it and change the state, it's value isn't changing. Second - I want to have a function execute when the state of the checkbox changes - and I bound a change function to the ID of the checkbox - but nothing is triggering. Using query 1.7.1
In doing some additional troubleshooting it seems that the problem is with binding the change event to the new "checkbox." No matter how I try to bind it - to the original ID, or any of the tz classes that are tied to the spans in the script - the change event doesn't trigger when the slider is clicked. Also doesn't work for click events.
there’s also this jQuery plugin called <a href="http://stefangabos.ro/jquery/zebra-transform/">Zebra_Transform</a> which transforms all the check boxes, radio buttons and select boxes on a page. it’s not as fancy as yours, but it is very very small (3KB) and works in all major browsers.
How to "Check all" or "Uncheck all" using a single button click???
To check or uncheck all using a single button
<input type="button" class="check" value="check all" />
<script>
$('input[type=checkbox]').tzCheckbox({
labels: [ 'Enable', 'Disable' ]
});
$(document).ready(function(){
$('.check:button').click(function(){
if(!$('.tzCheckBox').hasClass('checked'))
{
$('.tzCheckBox').addClass('checked');
$('.tzCheckBox').find('.tzCBContent').html('Enable');
$(this).val('uncheck all');
}
else
{
$('.tzCheckBox').removeClass('checked');
$('.tzCheckBox').find('.tzCBContent').html('Disable');
$(this).val('check all');
}
})
});
</script>
Your script is perfect but i can't take the value from checkbox and submit form onchange
Martin, you're the best. Thank you!
For later versions of Jquery I use 1.9.1 you need to change the javascript to the following
I think className has been depreciated, also there were some extra spaces in the class declaration
The entire code segment is
Thanks for the example best one I could find
+1 I rename className to class:
it doesn't run under IE8 http://stackoverflow.com/questions/17442311/tzcheckbox-expected-identifier-string-or-number#17442311
use this under ie8.
'class' : 'tzCheckBox'+(this.checked?' checked':''),
I think you have to use:
originalCheckBox.prop('checked',isChecked);
now instead of
originalCheckBox.attr('checked',isChecked);