Custom styled form elements are a common thing to see in a design. That’s because default form styles vary visually from browser to browser and OS to OS. It makes sense that we’d want these elements styled consistently. Styling them is pretty straightforward, with the exception of
select dropdowns which can be more complex. Recently, I ran into an unexpected problem when working on a site that needed a branded admin experience.
Styling Radio and Checkbox Buttons
There’s a simple method of styling radio buttons and checkboxes I’ve been using for a while. I first saw it from the people at Tuts+, and they provided this Pen demoing the technique. Briefly explained, we visually hide the
input for our radios/checkboxes and draw a new one using
:after pseudo elements on the
label element. CSS’
:checked selector allows us to toggle our styles based on if the
input is checked or not. This technique relies on appropriately marked up
labels, for example:
<div class=”form-element”> <input type=”checkbox” id=”click-me”> <label for=”click-me”>Click Me</label> </div>
Clicking the label (containing the fake checkbox styling) will toggle the state of the real checkbox that’s visually hidden.
Drupal’s Admin Interface
One thing I learned while working with some of Drupal’s admin interfaces is that they only supply the
input, and not an accompanying
label. This seemed especially true in tabled interfaces, where you’d check off rows of content and perform some action on the selected items. Since we’re hiding an
input that doesn’t have a
label to attach the visuals to, we just end up with a blank space. There were several options we had for how to address this issue.
1. Drop the Custom Styles
The simplest is to just rely on browser defaults for checkboxes and radios. It’s not a great option, but it is an affordable one for tight budgets.
2. Create the Missing Labels
This ended up being my first approach to fixing this, and became more akin to a game of Whack-a-Mole than I anticipated. After going through various preprocess functions, alters, and render functions I was still encountering inputs that were missing labels. Some I was never able to fully track down where the markup was coming from. Manually finding and fixing every missing label might be a viable solution if your website or application has only a handful of places you need to update. However this is not the most scalable solution, and if your product grows this can quickly become a financial black hole.
4. Drop the Custom Styles… for Older Browsers
In the end, this was the solution that won out. Using CSS Feature Queries and CSS’
Firefox was a surprise to me, as the documentation says it supports
appearance. However in practice what I got was a less appealing version of the browser default styles. Also surprisingly was by checking for only
-webkit-appearance support, Edge still gets our custom styles applied. This all sat well with me for a working solution. Every team and project has it’s own constraints, so your mileage may vary.