When you start to work on webpages that need to function well in other devices, you start to learn that certain native HTML elements aren't really made for touch. When using a mouse, you can be pretty precise with your mouse movements and your clicking. However, when you attempt to touch something, smaller elements will cause the user to miss often. There are some good articles on the interwebs on the recommended size of elements that will require touch, including some guidelines from Microsoft. One of the elements that I have been getting frustrated with recently is the check box. My fingers had a rough time clicking them on a tablet device.
So I decided to come up with something that would be easier for a user with a touch interface to use, but still act as a check box. Like most of my element redesign, I wanted to avoid using any JavaScript and rely on solely on CSS. Taking a look around the web and other places I decided to settle on an on/off switch looking element.
The first thing we want to define is the button HTML. First we define a container element for the class. We are going to use this element as the container and anchor for everything inside it. Next, we add a checkbox (because we still want to use the functionality of the checkbox for binding, form submitting, etc. I then added a "background" element that would span the entire width and change based on the input being checked or unchecked (I'll get to this more later). Lastly, we add a few elements to give it the "switch" feel. That is a label for "On", "Off", and label that is going to act as the "slider" for the switch. Our HTML is going to look like this:
So you might think it is odd that I am using labels for these elements, especially for the "slider". The reason that I do this, has to do with the "for" property of the label. By clicking on the label, it will click the element for you.*
So now that we have our structure designed we need to style everything to turn it into a toggle button. First we will style the container. We are going to use this to determine the size of everything. So we need to set the position it to be relative to give us an anchor for all the child elements, set overflow to hidden so nothing flows out of the container, and finally just set a nice border.
Next, lets style the check box. We really just want to make it invisible, and not effect the rest of the HTML.
Now we want to style the on, off, slider, and background. I include these all together because they all need two styles each. One for checked and one for unchecked. So let's start with the first state which is unchecked. For the background we are going to set it as the entire width and height of the container (including the border radius), and set the background-color for when the we are unchecked which I will set to red. I am going to also set the transition of the background color which will give a smoother transition feel.
The slider will be defaulted to the left side of the toggle, with the on element hidden off the left, and the off displayed to the right of the slider. Instead of just hiding the elements, I want to make it look smoother by moving objects to the left and right. So I added a transition to the elements below.
Here is the end result:
I think the best way to use this would be to create a widget, directive, or whatever your JS framework supports. With a little bit of extra JS you can add some additional classes such as a class to the entire module and style the entire element differently.
*If you are putting this on the web, you should really think about accessibility. Having those extra labels for one input might confuse some screen readers, and by extension your users. A couple of extra click handlers for the labels won't kill anyone.
This episode is almost 20 years old. |
So I decided to come up with something that would be easier for a user with a touch interface to use, but still act as a check box. Like most of my element redesign, I wanted to avoid using any JavaScript and rely on solely on CSS. Taking a look around the web and other places I decided to settle on an on/off switch looking element.
The first thing we want to define is the button HTML. First we define a container element for the class. We are going to use this element as the container and anchor for everything inside it. Next, we add a checkbox (because we still want to use the functionality of the checkbox for binding, form submitting, etc. I then added a "background" element that would span the entire width and change based on the input being checked or unchecked (I'll get to this more later). Lastly, we add a few elements to give it the "switch" feel. That is a label for "On", "Off", and label that is going to act as the "slider" for the switch. Our HTML is going to look like this:
<span class='toggleContainer'> <input class='toggleInput' type='checkbox' id='chk'></input> <span class='background'></span> <label class='slider' for='chk'></label> <label class='on' for='chk'>On</label> <label class='off' for='chk'>Off</label> </span>
So you might think it is odd that I am using labels for these elements, especially for the "slider". The reason that I do this, has to do with the "for" property of the label. By clicking on the label, it will click the element for you.*
So now that we have our structure designed we need to style everything to turn it into a toggle button. First we will style the container. We are going to use this to determine the size of everything. So we need to set the position it to be relative to give us an anchor for all the child elements, set overflow to hidden so nothing flows out of the container, and finally just set a nice border.
.toggleContainer{ border: 1px solid white; border-radius:6px; display:inline-block; width:50px; height:20px; position: relative; overflow:hidden; }
Next, lets style the check box. We really just want to make it invisible, and not effect the rest of the HTML.
.toggleInput{ position: absolute; opacity: 0; }
Now we want to style the on, off, slider, and background. I include these all together because they all need two styles each. One for checked and one for unchecked. So let's start with the first state which is unchecked. For the background we are going to set it as the entire width and height of the container (including the border radius), and set the background-color for when the we are unchecked which I will set to red. I am going to also set the transition of the background color which will give a smoother transition feel.
.toggleContainer .background { position: absolute; width: 100%; height: 100%; border-radius: 6px; background-color: red; opacity: 0.2; -moz-transition: background-color .3s; -webkit-transition: background-color .3s; transition: background-color .3s; }
The slider will be defaulted to the left side of the toggle, with the on element hidden off the left, and the off displayed to the right of the slider. Instead of just hiding the elements, I want to make it look smoother by moving objects to the left and right. So I added a transition to the elements below.
.toggleContainer .toggleInput ~ .slider { position: absolute; width: 45%; height: 100%; content: ""; background-color: white; border-radius: 6px; display: inline-block; z-index: 1; left: 0; -moz-transition: left 0.3s; -webkit-transition: left 0.3s; transition: left 0.3s; } .toggleContainer .toggleInput ~ .off, .toggleContainer .toggleInput ~ .on { width: 50%; position: relative; z-index: 10; display: inline-block; overflow: hidden; height: 100%; top: 50%; margin-top: -8px; } .toggleContainer .toggleInput ~ .on { left: -50%; float: left; -moz-transition: left 0.3s; -webkit-transition: left 0.3s; transition: left 0.3s; color: green; } .toggleContainer .toggleInput ~ .off { right: 0; -moz-transition: right 0.3s; -webkit-transition: right 0.3s; transition: right 0.3s; float: right; color: red; }Now that we have a default style, we need to add styles for when the element is checked. To do this we can use the :checked css selector and apply the styles that we want to change. Mostly we want to move everything to the right which gives the appearance of a switch being moved. The only exception is the background which we will change from red to green.
.toggleContainer .toggleInput:checked ~ .background { background-color: green; -moz-transition: background-color 0.3s; -webkit-transition: background-color 0.3s; transition: background-color 0.3s; } .toggleContainer .toggleInput:checked ~ .slider { left: 55%; -moz-transition: left 0.3s; -webkit-transition: left 0.3s; transition: left 0.3s; } .toggleContainer .toggleInput:checked ~ .on { left: 5px; -moz-transition: left 0.3s; -webkit-transition: left 0.3s; transition: left 0.3s; } .toggleContainer .toggleInput:checked ~ .off { right: -50%; -moz-transition: right 0.3s; -webkit-transition: right 0.3s; transition: right 0.3s; }
Here is the end result:
I think the best way to use this would be to create a widget, directive, or whatever your JS framework supports. With a little bit of extra JS you can add some additional classes such as a class to the entire module and style the entire element differently.
*If you are putting this on the web, you should really think about accessibility. Having those extra labels for one input might confuse some screen readers, and by extension your users. A couple of extra click handlers for the labels won't kill anyone.
No comments:
Post a Comment