Checkboxes can be excellent buttons
Tags: javascript, accessibiliy, forms, checkboxes
Published: 2020-09-22 20:35:48

---
title: Checkboxes can be excellent buttons
published: true
description: A quick tip how to react to changes of checkboxes without having to traverse the DOM or add a lot of handlers.
tags: javascript,accessibiliy,forms,checkboxes
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/wz3u9l1gaphnr49d8luh.jpg
---

I like checkboxes - they give me a simple way in a tool to turn modes on and off without using much space. I especially like it that you can style them with CSS without jumping through hoops like you need to with buttons. 

I like to use checkboxes as buttons. And here's how.

A checkbox is a binary state. It is checked or not. So instead of reading out the state in an event handler, I tend to read the checked property.

## What does this mean? 

Take a look at [this codepen](https://codepen.io/codepo8/pen/RwaEVLa?editors=1111).

{% codepen https://codepen.io/codepo8/pen/RwaEVLa %} 

Looks neat and works. Let's take a look at the how. 

The first thing I do is to ensure that my code is accessible. That's why every checkbox needs a label to explain to assistive technology like screen readers what it is. 

```xml
<input type="checkbox" id="doublewide">
<label for="doublewide">Double width</label>
<input type="checkbox" id="doublehigh"> 
<label for="doublehigh">Double height</label>
<div id="box"></div>
```

This also has the real practical upshot that when I click on the label text (which is normally much bigger than the checkbox) I change the state of the checkbox. This also helps a lot on mobile devices. From a look and feel point of view, it means I don't need the checkboxes any longer, so let's hide them off screen:

```CSS
/* Hide checkboxes */
[type=checkbox] {
  position: absolute;
  left: -50vw;
}
```

We style the labels to look "not selected" or greyed out:

```CSS
label {
  background: #ccc;
  padding: 5px 10px;
  color: #333;
}

```
And we colour them when the checkbox is checked (let's also add a transition to make it look smoother): 

```CSS
/* Selected */
[type=checkbox]:checked + label {
  background: #369;
  color: #fff;
  transition: 400ms;
}
```

>Quick aside: you can also style them to interact to keyboard users focusing on the checkboxes and to mouse interaction on the label itself:

```CSS
[type=checkbox]:focus + label {
  background: #9cf;
  color: #000;
}
[type=checkbox] + label:hover {
  background: #9cf;
  color: #000;
}
```
Now on to the JavaScript interaction. First, we need some references to the checkbox DOM elements (it makes sense to cache that as reading the DOM is expensive).

```Javascript
const dw = document.querySelector('#doublewide');
const dh = document.querySelector('#doublehigh');
```

We'll define a change function to be called every time one of the checkboxes is clicked. In this one we read out the checked state of the checkboxes and react accordingly. In this case, changing the width of the box. 

```Javascript
const change = _ => {
    box.style.width = dw.checked ? '100px' : '50px';
    box.style.height = dh.checked ? '100px' : '50px';
 };
```

The last thing to do is to add Event Listeners to the checkboxes to call the change function:

```JavaScript
dw.addEventListener('click', change);
dh.addEventListener('click', change);
```

We could even use Event Delegation instead and apply this to all checkboxes. That way we don't need to add a lot of listeners and we can dynamically add and remove checkboxes without having to re-iterate over them.

```Javascript
document.body.addEventListener('click', e => {
  if (e.target.type === 'checkbox') {
    change();
  }
})
```

Nothing magical here, but I really like the fact that instead of having to store the state myself, all I need to do is read the checked state and leave the interaction to the browser.

---

Photo by [TeroVesalainen](https://www.shutterstock.com/g/terovesalainen)