iPhone Checkboxes Using MooTools

By  on  
iPhone Checkboxes

One of the sweet user interface enhancements provided by Apple's iPhone is their checkbox-slider functionality. Thomas Reynolds recently released a jQuery plugin that allows you to make your checkboxes look like iPhone sliders. Here's how to implement that functionality using the beloved MooTools JavaScript framework.


<h2>Off by default</h2>
<p><input type="checkbox" /></p>
<h2>On by default</h2>
<p><input type="checkbox" checked="checked" /></p>

This is how the XHTML code is initially embedded within the page. MooTools will change this drastically.


.iPhoneCheckContainer{ position:relative; width:85px; height:27px; cursor:pointer; overflow:hidden;  }
.iPhoneCheckContainer input{ position:absolute; top:5px; left:30px;  }
.iPhoneCheckHandle{ display:block; height:27px; width:39px; cursor:pointer; position:absolute; top:0; left:0;  }
.iPhoneCheckHandle .iPhoneCheckHandleBG{ position:absolute; width:5px; height:100%; top:0; left:0; z-index:1;  }
.iPhoneCheckHandle .iPhoneCheckHandleSlider{ position:absolute; top:0; left:0; height:27px; width:39px; background:url(iphone-slider.png) no-repeat; z-index:2;  }
label.iPhoneCheckLabelOn,label.iPhoneCheckLabelOff{ font-size:17px; line-height:17px; font-weight:bold; font-family:Helvetica Neue,Arial,Helvetica,sans-serif; text-transform:uppercase; cursor:pointer; display:block; height:22px; position:absolute; width:52px; top:0;  }
label.iPhoneCheckLabelOn{ color:#fff; background:url(iphone-on.png) no-repeat; text-shadow:0px 0px 2px rgba(0,0,0,0.6); left:0; padding:5px 0 0 8px;  }
label.iPhoneCheckLabelOff{ color:#8B8B8B; background:url(iphone-off.png) no-repeat right 0; text-shadow:0px 0px 2px rgba(255,255,255,0.6); text-align:right; right:0; padding:5px 8px 0 0;  }

The CSS is pretty simple but notice we have to define classes for each state.

The MooTools JavaScript

	(function($) {

		this.IPhoneCheckboxes = new Class({

			Implements: [Options],

			options: {
				checkedLabel: 'ON',
				uncheckedLabel: 'OFF',
				background: '#fff',
				containerClass: 'iPhoneCheckContainer',
				labelOnClass: 'iPhoneCheckLabelOn',
				labelOffClass: 'iPhoneCheckLabelOff',
				handleClass: 'iPhoneCheckHandle',
				handleBGClass: 'iPhoneCheckHandleBG',
				handleSliderClass: 'iPhoneCheckHandleSlider',
				elements: 'input[type=checkbox]'

			initialize: function(options) {
				//set options
				this.elements = $$(this.options.elements);
				//observe checkboxes
				this.elements.each(function(el) {

			//a method that does whatever you want
			observe: function(el) {
				//turn off opacity
				//create wrapper div
				var wrap = new Element('div',{
					'class': this.options.containerClass
				//inject this checkbox into it
				//now create subsquent divs and labels
				var handle = new Element('div',{'class':this.options.handleClass}).inject(wrap);
				var handlebg = new Element('div',{'class':this.options.handleBGClass,'style':this.options.background}).inject(handle);
				var handleSlider = new Element('div',{'class':this.options.handleSliderClass}).inject(handle);
				var offLabel = new Element('label',{'class':this.options.labelOffClass,text:this.options.uncheckedLabel}).inject(wrap);
				var onLabel = new Element('label',{'class':this.options.labelOnClass,text:this.options.checkedLabel}).inject(wrap);
				var rightSide = wrap.getSize().x - 39;
				//fx instances
				el.offFx = new Fx.Tween(offLabel,{'property':'opacity','duration':200});
				el.onFx = new Fx.Tween(onLabel,{'property':'opacity','duration':200});
				//mouseup / event listening
				wrap.addEvent('mouseup',function() {
					var is_onstate = !el.checked; //originally 0
					var new_left = (is_onstate ? rightSide : 0);
					var bg_left = (is_onstate ? 34 : 0);
					new Fx.Tween(handle,{
						duration: 100,
						'property': 'left',
						onComplete: function() {
					//label animations
					if(is_onstate) {
					else {
					//set checked
				//initial load
				} else {


	/* usage */
	var chx = new IPhoneCheckboxes();

The class allows for customization of which events get iPhone-ized, the label text statements, and what each CSS class is called. Besides those given options, you have nothing else to do unless you plan on hacking the class completely.

Sweet, no? Funny how we emulate functionality from an inferior technology (mobile browser). I would consider this functionality "proof of concept," as increasing the font-size may cause issues in some browsers. Cool effect though -- consider it for your websites!

Recent Features

  • By
    fetch API

    One of the worst kept secrets about AJAX on the web is that the underlying API for it, XMLHttpRequest, wasn't really made for what we've been using it for.  We've done well to create elegant APIs around XHR but we know we can do better.  Our effort to...

  • By
    Page Visibility API

    One event that's always been lacking within the document is a signal for when the user is looking at a given tab, or another tab. When does the user switch off our site to look at something else? When do they come back?

Incredible Demos

  • By
    CSS Fixed Positioning

    When you want to keep an element in the same spot in the viewport no matter where on the page the user is, CSS's fixed-positioning functionality is what you need. The CSS Above we set our element 2% from both the top and right hand side of the...

  • By
    Fix Anchor URLs Using MooTools 1.2

    The administrative control panel I build for my customers features FCKEditor, a powerful WYSIWYG editor that allows the customer to add links, bold text, create ordered lists, and so on. I provide training and documentation to the customers but many times they simply forget to...


  1. Darkimmortal

    Make the text unselectable or it gets selected after a couple of clicks :P

  2. Chris

    Like it – but in my opinion it should also work with dragging the knob.

  3. For doing what Darkimmortal said someone can add the following events:

    //IE uses the select start event =>
      return false;
    //Any other browser is happy with the mouse down =>
     return false;
     //does whatever it is planned to do

    Nice eye candy, but it would be harder for simple PC users to get, if it needed them to scroll that div by themselves.

  4. //damn, for this example you should change the click to the mouseup function in the class xD

  5. wow this is really cool…good work David

  6. the spacing of the handle is a little messed up in IE7 and IE6…other than that it’s pretty cool…

  7. It’s nice, but I agree, it would be even better if it could be dragged. That’s the first thing I tried to do

  8. after reading the code I see that you create a new Fx instance on every mouse up. You should create a single object like you did with the other Fx, you can even set the ‘link’ option to cancel. You can can make bg_left a class variable so it’s accessible in the onComplete function

  9. @olivier: Good point — I’ll update that.

  10. Zoran

    If i had to choose word for this i would go with cute or sweet… hahaha… Good work by the way, i like it very much

  11. Check out http://reaktivo.com/mt/mooswitch I made a year ago…

  12. Ga

    REALLY NICE!!!!!!!! Thx David!!

  13. Alan


    That is really cool. I like the options you have available

  14. Charlie Skapes

    This is awesome! Great work David! Can’t wait to see what you come up with next!

  15. is this thing on? it ‘ate’ my comment!

  16. right. anyway – it’s a handy little class and all that, just a small change as I needed it to call a function on the change of state, hopefully posting it this time won’t have it disappear…

    options: {
        changeEvent: $empty, // add an empty event function

    end of the wrap.addEvent('mouseup',function() { anon function:

    //set checked
        this.options.changeEvent.run([is_onstate, el]);

    usage exmaple to enable / disable products from a list via ajax:

    [input type="checkbox" data-id="44" /]
    new IPhoneCheckboxes({
        changeEvent: function(status, el) {
            new Request({
                url: "somefile.php"
                method: "get",
                onComplete: function() {
            }).send("a=productStatus&id="+el.get("data-id") + "&status=" + (status) ? "live" : "disabled");
  17. well twice already I cannot post the suggested change so I am putting it into a .txt file.
    the idea is, as great as the class is, i needed it to be able to call a function with the checkbox state on each change, as well as pass on the original element to that function (in order to be able to update a DB via ajax)

    resulting code looks like this: http://fragged.org/dev/iphoneCheckboxChange.txt (a quick change rather than implementing Events).


  18. oh heh, and now they are here. can you delete the dupes please. http://fragged.org/dev/iphoneCheckboxChange.txt now contains an updated version which also addresses some issues with non-movers on click when there are MANY checkboxes on screen (30+)

  19. vocal

    so,this is very cool. I love it.

    but I find a small problem: for the styles of of outer divs of the example, such as id=”content” or class=”content” or id=”wrap” and so on, if i add a margin property at them, the event will be invalid, it will not change status when you click at the button. you can test by adding “margin:10px” to #content or other div, it doesn’t work.

    I wanna know why it comes with this. is it a little bug? or a margin property can’t be use here?

  20. thnx for all your good scripts!
    this one I have a problem installing, it hangs when loaded. I tried a demo page seperated from any other content and it still hangs when it comes to #fff. Tried you mootools version and it still stops..

    Can you help me out? my javascript knowledge ain’t that good with debugging… only simple scripts I am able to implement and I am working from examples..

  21. Dipen

    i got following error when using iPhone-CheckBox…..”handlebg.hide is not a function” :(

  22. Dipen

    i got this error when i click on [on or off] button

  23. olivier refalo

    you need to change the event from mousedown to click for this to work on Safari…

  24. That have a conflict in off to on On Safari Web Browser ???

  25. Fixed the demo. Sorry everyone!

  26. Demo page doesn’t work.

  27. olivier refalo

    Demo doesn’t work under safari, the switch flips sides only once…

  28. Flipping only once on Firefox and you still haven’t made the text unselectable :P

  29. Patched up the switching issues and updated my post’s code.

  30. Reinier

    I found few years ago an example like this one.. only with on and off buttons from a old television..was pretty funny!

    Here demo doesn’t work either.. it worked before, only when installing I had the same problem as Dipen.

  31. Reinier

    oops sorry demo works now..

  32. Olivier Refalo

    Actually, it still behaves funny under IE7.. looks like a layer priority issue because the widget seems to be working as designed…

  33. Olivier Refalo

    please change the CSS to the following to fix z-index issue on IE7

    .iPhoneCheckHandle {
    	display: block;
    	height: 27px;
    	width: 39px;
    	cursor: pointer;
    	position: absolute;
    	top: 0;
    	left: 0;
    	z-index: 2;   <<--- ADD THIS
  34. Amanada

    Loved it These are checkboxes and i was wondering can these be achieved on list items?


  35. Hi David,

    Here’s challenge for you. Can this script be made to work with a group of radio buttons so that when one is clicked, it slides to on, and the others automatically slide to off?



  36. Notice on the demo video, they use the iPhone sliders? I don’t think they are yours, but still kinda neat!


  37. ayoub

    it looks great but it dosen’t work with the latest version of mootools.
    i’m having issues with handlebg.hide is not a function

  38. Samuel

    And it also doesnt work since a few days in the latest IE 9 !? having big troubles with that… the first checkbox is hide and all others are in normal html style. Could someone help me? i have to deactivate it now because of the missing first checkbox :-(

  39. Samuel

    iam sorry! not the first one is hide, the activated ones not visible.

  40. Samuel

    Update from Mootools 1.2 to mootools-core-1.4.1-full-compat worked for me!

  41. Igor Fernandes

    Someone can post the update code for mootools 1.4?

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!