How to create a custom checkbox

2020-03-05
  • tutorials
  • frontend
  • css

This post is both to preserve a quick experiment for later use and to show how easy it is to implement a custom checkbox.

Note: As this does not follow semantic HTML, no meaning is conveyed to users of assistive technologies with e.g. screen readers. Make sure to add the appropriate ARIA labels.

See the Pen Custom checkbox by Marc Ed Raffalli (@marc-ed-raffalli) on CodePen.

.checkbox {
  position: relative;
  padding: 8px 8px 8px 40px;
  cursor: pointer;
  border: 1px solid #ccc;
  border-radius: 2px;
  margin: .25rem 0;
  user-select: none;
}

.checkbox:hover {
  background-color: rgba(0, 0, 0, .15);
}

.checkbox:hover:before {
  border-right: 1px solid #999;
}

.checkbox:active {
  background-color: rgba(0, 0, 0, .25);
}

.checkbox:before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;

  width: 30px;
  height: 30px;
  margin: auto;
  line-height: 30px;
  border-right: 1px solid #ccc;
  text-align: center;
  font-size: 1.25rem;
}

.checkbox.checked:before {
  content: '✓';
}
<div class="checkbox">Default state</div>
<div class="checkbox checked">Checked state</div>
document.querySelectorAll('.checkbox').forEach(e => {
  e.addEventListener('click', toggleCheckbox);
  e.addEventListener('keypress', keyPressProxy);
});

function keyPressProxy(e) {
  e.preventDefault();

  if (e.code === 'Enter' || e.code === 'Space') {
    toggleCheckbox(e);
  }
}

function toggleCheckbox(e) {
  e.preventDefault();
  e.stopPropagation();

  const elt = e.target;

  if (elt.classList.contains('checked')) {
    elt.classList.remove('checked');
    return;
  }

  elt.classList.add('checked');
}