Skip to content

Breakdown

CSS

set to the 'pre' side of the html on the page via the gear icon

erase the orange on initial page load / whipe so the 'in between' of state !checked doesn't show orange as a kind of 'lingering' after

css
.checkbox-card {
  outline: 2px solid #333 !important;
  border: none;
  transition: background-color 0.2s, outline 0.2s;
}

.checkbox-card:focus,
.checkbox-card:active {
  outline: none;
  border: none;
}

JS

javascript
window.addEventListener('load', () => {
  document.querySelectorAll('.checkbox-card').forEach(card => {
    updateCard(card);
    card.addEventListener('pointerdown', (e) => {
      e.preventDefault(); // stops focus/blur or accidental drag events
      card.classList.toggle('checked');
      updateCard(card);
    });
  });
});

function styleCheckedCard(el) {
  el.style.setProperty('--background-color', '#aaff008c');
  el.style.backgroundColor = '#aaff008c';
  el.style.outline = '2px solid #333';
  el.style.outlineOffset = '-2px';

  if (!el.querySelector('.checkmark')) {
    const check = document.createElement('span');
    check.textContent = '✔️';
    check.className = 'checkmark';
    check.style.position = 'absolute';
    check.style.top = '14px';
    check.style.right = '14px';
    check.style.fontSize = '10px';
    el.style.position = 'relative';
    el.appendChild(check);
  }
}

function unstyleCard(el) {
  el.style.removeProperty('--background-color');
  el.style.backgroundColor = '';
  el.style.outline = 'none';
  const existingCheck = el.querySelector('.checkmark');
  if (existingCheck) existingCheck.remove();
}

function updateCard(el) {
  if (el.classList.contains('checked')) {
    styleCheckedCard(el);
  } else {
    unstyleCard(el);
  }
}

Explore and learn. Released under the MIT License.