A couple weeks ago while browsing reddit I stumbled across a very cool Android UI button that I thought was genius. https://github.com/cdflynn/crossview In particular this element would be great for lists where you want to add or remove options, like a choose your toppings list for a burger (e.g. add or remove toppings).
I thought that this would be a great time to learn about CSS transitions and make a version of the element in HTML5 and CSS with as little JavaScript as I possibly could. My first few attempts managed to get the cross to appear and then when applying
tranform: rotate(45deg);
I got a nasty little issue because the center of the 2 elements that I was rotating were in different places and it just didn’t work at all. I contacted my CSS guru friend over at scottlittle.me and asked for some advice. He pointed me towards using a label and attaching it to a checkbox to handle the toggle states. To handle the centering of the cross we figured out a method of using ::before and ::after pseudo elements.
It took me a little while to work out the details but I managed to come up with something that worked well. Using a combination of the label, :before and :after pseudo selectors in addition to a :checked selector I was able to make the whole element work without any JavaScript. An added bonus to the methods I found was that it scales very well simply by changing the width and height of the label. I was hoping to be able to wrap the whole thing up in some easy to use package but when I looked at Web Components support on Can I Use, things looked quite abysmal. I may eventually look to wrap this up as a Polymer Element once Polymer hits 1.0 (breaking changes are expected between 0.9 and 1.0).
Here is the final product:
Go ahead and click on it to go between adding or removing an option. And since this is just a hidden checkbox plus a label it will submit just like a checkbox!
I don’t have IE9 to run this on but looking at caniuse.com and MDN, this should support everything going back to IE9 (plus I added the necessary vendor prefixes for Safari and IE)
*Feature image taken from cdflynn’s github, linked above.
Here’s the css I used:
input.add-remove[type=checkbox]{
display:none;
}
input.add-remove[type=checkbox] + label{
width:40px;
height:40px;
display:inline-block;
position:relative;
z-index:1;
}
input.add-remove[type=checkbox] + label:before {
content:"";
left: 50%;
width: 10%;
margin-left: -5%;
position:absolute;
z-index:-1;
height: 100%;
color: #ccc;
background:red;
font-style: italic;
-webkit-transition:-webkit-transform .3s;
transition:transform .3s;
}
input.add-remove[type=checkbox] + label:after {
content:"";
position:absolute;
top: 50%;
height: 10%;
margin-top: -5%;
width: 100%;
background:red;
z-index:-1;
color: #ccc;
font-style: italic;
-webkit-transition:-webkit-transform .3s;
transition:transform .3s;
}
input.add-remove[type=checkbox]:checked + label {
color: #f00;
font-style: normal;
z-index:1;
}
input.add-remove[type=checkbox]:checked + label:before {
-webkit-transform:rotate(-45deg);
-ms-transform:rotate(-45deg);
transform:rotate(-45deg);
}
input.add-remove[type=checkbox]:checked + label:after {
-webkit-transform:rotate(135deg);
-ms-transform:rotate(135deg);
transform:rotate(135deg);
}
You can get this and the alternate version (remove-add and add-remove) together from my Github project for this element here.
Super clever!