Using CSS Webkit-Appearance To Style Checkbox ::after Pseudo-Element
Last weekend, my mind was blown by Divya Sasidharan, who mentioned that you could use webkit-appearance
to add custom CSS styling to native form elements. Since then, I've been on the lookout for examples of this; and, just yesterday, I came across a fascinating checkbox on the Coolors color-palette generator site. In their Settings panel, not only did they use -webkit-appearance:none
to style their checkboxes, they were also using the ::after
pseudo-element! Hold the phone! I had no idea that the checkbox even had pseudo-elements. As such, I had to try this technique out for myself.
Run this demo in my JavaScript Demos project on GitHub.
View this code in my JavaScript Demos project on GitHub.
The Coolors' checkboxes are styled to resemble a "switch toggle", much like you would see in an iOS application. The input
element is the "track" of the toggle; and, the input::after
is the "thumb". From what I've been Googling, most input
elements don't support pseudo-elements; but, apparently, the type="checkbox"
has good, though possibly undocumented, cross-browser support? My Google-fu is failing me on this matter.
Anyway, here's my attempt to recreate the custom CSS styling I've seen on Coolors checkbox:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>
Using CSS Webkit-Appearance To Style Checkbox ::after Pseudo-Element
</title>
</head>
<body>
<h1>
Using CSS Webkit-Appearance To Style Checkbox ::after Pseudo-Element
</h1>
<style type="text/css">
label {
align-items: center ;
cursor: pointer ;
display: flex ;
}
label input {
margin: 0px 0px 0px 10px ;
}
/*
Only apply custom styles to browsers that are going to support them. This is
important because even old browsers will apply SOME of these CSS properties;
and, we don't want to create Frankenstein checkboxes.
*/
@supports ( appearance: none ) or ( -moz-appearance: none ) or ( -webkit-appearance: none ) {
input.custom {
appearance: none ;
-moz-appearance: none ;
-webkit-appearance: none ;
border: 2px solid currentcolor ;
border-radius: 52px 52px 52px 52px ;
box-sizing: content-box ;
color: #999999 ;
height: 18px ;
padding: 2px 2px 2px 2px ;
transition-duration: 300ms ;
transition-property: border-color, color ; /* Safari needed border-color. */
transition-timing-function: ease ;
width: 52px ;
}
input.custom:checked {
color: #ff3366 ;
}
/*
NOTE: The ::after pseudo-selector is being applied to the INPUT itself,
not a parent element. I had no idea this even works! I can't find any
documented support on this (just some StackOverflow threads).
*/
input.custom::after {
background-color: currentcolor ;
border-radius: 10px 10px 10px 10px ;
content: "" ;
display: block ;
height: 18px ;
transform: translateX( 0px ) ;
transition: transform 300ms ease ;
width: 24px ;
}
input.custom:checked::after {
transform: translateX( 27px ) ;
}
}
</style>
<p>
<label for="checkbox1">
Default checkbox:
<input id="checkbox1" type="checkbox" />
</label>
</p>
<p>
<label for="checkbox2">
Webkit-Appearance checkbox:
<input id="checkbox2" type="checkbox" class="custom" />
</label>
</p>
</body>
</html>
As you can see, I'm using the @supports
directive to ensure we only apply the custom CSS to browsers that will fully support it. This way, we don't end up with a wonky-looking checkbox that has some of the custom CSS, but that doesn't deliver the expected user experience (UX).
Then, within the @supports
block, I'm applying custom CSS to both the input
checkbox and its ::after
pseudo-element, styling both the checked and unchecked states. And, when we run this in the browser, we get the following output:
Cool beans!! This works quite nicely on Chrome, Firefox, Safari, and Edge (for Mac). It even works swimingly on my Apple iPhone mobile Safari and mobile Chrome (which I think both use Webkit under the hood). And, of course, for browsers that don't support either the @supports
block or the webkit-appearance
, we just get the browser's native user-agent styling:
That's what's so exciting about this technique! It's minimal effort to add the custom CSS styling to the checkbox; and, it degrades quite gracefully! I am loving the world of progressive enhancement; and, finally releasing the archaic notion that every browser has to have pixel-perfect design. What an exciting time to be alive!
Want to use code from this post? Check out the license.
Reader Comments
Super cool. Is there a lib to refresh all inputs and selects to this style?
@Karl,
I am not sure. I would guess there is, though :) People have been trying to style inputs since the dawn of time :D :D :D
Ben. Isn't this what I used in my previous codepen? Actually, I think I used:
Here is another example of a customised checkbox. I must admit, I did not create this one. But, I was so impressed by it, that I forked it. I must get around to adding a credit to it:
https://codepen.io/charles1971/pen/JzKPRQ
@Charles,
Ha ha, oh man -- I think when I looked at your last CodePen, I saw the "Upload" and the "Select" and I think my brain totally skipped over what you were doing with the Radio buttons :D I think -- because I didn't even realize it was possible -- my brain didn't even fully register what you were doing.
Oh man, sorry about that! I didn't mean to disregard what you did - it was just more advanced than what my brain was ready to accept :P
@Charles,
Yooo, that little puff of smoke on the checkbox in your latest CodePan -- dang!!
Ben. No worries. I am always missing stuff. I think it has something to do with data overload. I just don't think our brains have had enough time to evolve, when it comes to technology. We are zapped from every angle with digital information.
Anyway, I am sure that there are clever CSS gurus, building customised form element libraries, as we speak!
After all, with:
The sky's the limit...
Yes. I think the guy made the moon/sun toggle for a dark/light mode theme switch.
Pretty awesome stuff!
Actually, I think it is a light bulb.
I have another one somewhere, which depicts a sun morphing into a moon!
@Charles,
It's just great that all this web stuff continues to be such a source of excitement!