Styling a group of checkboxes as a dropdown via CSS and JavaScript

The following demonstrates how to create a dropdown list based on a list of checkbox elements. You can view a complete example of how this works at the following fiddle: http://jsfiddle.net/Terkildsen/mTSLa/

In the following I will walk you through the code.

First, I start by creating the HTML:

    <div class="dropdown">
        Choose city
        <ul class="dropdown-list">
            <li>
                <label>
                    <input type="checkbox" value="Vejle" name="city" />Vejle</label></li>
            <li>
                <label>
                    <input type="checkbox" value="Horsens" name="city" />Horsens</label></li>
            <li>
                <label>
                    <input type="checkbox" value="Kolding" name="city" />Kolding</label></li>
            <li>
                <label>
                    <input type="checkbox" value="Fredericia" name="city" />Fredericia</label></li>
        </ul>
    </div>

There’s not much to say about the HTML above. I use a “dropdown” div to contain the entire dropdown – including the default text that is displayed when the checkbox list is hidden. I then assign a “dropdown-list” class to the list of checkboxes.

Then, I start styling the dropdown:

.dropdown {
    width: 200px;
    border: 1px solid silver;
    cursor: pointer; /* use correct mouse pointer when hovering over the dropdown */
    padding: 10px;
    position: relative;
    margin: 0 auto;
    -webkit-touch-callout: none;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

In the CSS above I start by styling the entire dropdown. I provide the dropdown with a width of 200px, some padding and a border to make the dropdown resemble a normal select-list.

Notice that the usage of the “user-select: none;” prevents the user from accidentally highlighting the text in the dropdown.

/* Display CSS arrow to the right of the dropdown text */
.dropdown:after {
    content:'';
    height: 0;
    position: absolute;
    width: 0;
    border: 6px solid transparent;
    border-top-color: #000;
    top: 50%;
    right: 10px;
    margin-top: -3px;
}

Instead of inserting an image to display an arrow in order to indicate that this dropdown can be clicked on, I use a small CSS-trick that will display an arrow using a border-property. You can read more about how this is done in the following blogpost: https://pterkildsen.com/2012/09/16/creating-arrows-using-css/

/* Reverse the CSS arrow when the dropdown is active */
.dropdown.is-active:after {
    border-bottom-color: #000;
    border-top-color: #fff;
    margin-top: -9px;
}

When the user activates the dropdown, the CSS above reverses the direction of the CSS-arrow. It does this by applying the white background-color to the “border-top-color”-property so that this part of the border is hidden, and then displays the bottom part of the border by assigning a black color to the “border-bottom-color”-property.

.dropdown-list {
    list-style: none;
    margin: 0;
    padding: 0;
    position: absolute;
    top: 100%; /* align the dropdown right below the dropdown text */
    border: inherit;
    border-top: none;
    left: -1px; /* align the dropdown to the left */
    right: -1px; /* align the dropdown to the right */
    opacity: 0; /* hide the dropdown */
    -webkit-transition: opacity 0.4s ease-in-out;
    -moz-transition: opacity 0.4s ease-in-out;
    -o-transition: opacity 0.4s ease-in-out;
    -ms-transition: opacity 0.4s ease-in-out;
    transition: opacity 0.4s ease-in-out;
    pointer-events: none; /* avoid mouse click events inside the dropdown */
}

I then style the list of checkboxes. There are a couple of important issues here. First of all, I use the “opacity”-property to hide and display the checkbox-list. And secondly, I use the “pointer-events: none” to prevent click events from happening in the checkbox-list – which would accidentally hide it.

.is-active .dropdown-list {
    opacity: 1; /* display the dropdown */
    pointer-events: auto; /* make sure that the user still can select checkboxes */
}

The is-active class is applied to the checkbox-list whenever the user clicks on the “dropdown-selector”. This class displays the checkbox-list by setting the “opacity”-property to 1 and it also makes sure that the user still can select the checkboxes by setting “pointer-events: auto;”

.dropdown-list li label {
    display: block;
    border-bottom: 1px solid silver;
    padding: 10px;
    -webkit-transition: all 0.2s ease-out;
    -moz-transition: all 0.2s ease-out;
    -o-transition: all 0.2s ease-out;
    -ms-transition: all 0.2s ease-out;
    transition: all 0.2s ease-out;
}

.dropdown-list li label:hover {
    background-color: #c41230;
    color: white;
}

And then finally, I just add some finishing touches to the labels inside the checkbox-list.

In order for this to work, I add a couple of lines of jQuery:

         $(function () {
            $(".dropdown").click(function () {
                $(this).toggleClass("is-active");
            });

            $(".dropdown ul").click(function (e) {
                e.stopPropagation();
            });
        });

The code above detects the click event on the “dropdown”-div – which will toggle the “is-active” class. It also captures the click-event on the list of checkboxes in order to make sure that this doesn’t accidentally close the dropdown.

This code has been tested in Internet Explorer 9+, the latest version of Mozilla Firefox and Google Chrome. I have also tested it on iPhone and iPad. Seems to be working just fine. However, please notice that I’ve had some issues with jsfiddle and Internet Explorer. The code works fine without jsfiddle, though.