Component Library

← Back to gallery

Ordered checklist

Category: Tables & lists · Tags: checklist, tasks, progress, ordered-list, todo

Launch checklist

2 of 5 steps done

How to use it

Use for a short, ordered set of tasks a person works through, such as a launch or onboarding checklist. Do not use it for unordered preferences (use a checkbox group) or for steps the system tracks on its own (use a progress stepper). After copying, give each checkbox a unique id matched by its label, and save the checked state on your server if progress must persist; the demo keeps it only on the page.

Accessibility

The steps are an ordered list (<ol>) so their numbers are announced, and each step is a native checkbox with its own <label>. A completed step is shown three ways, never by colour alone: the box is checked, the text is struck through, and "(done)" is added to the label text so it is read aloud and survives without CSS. A polite aria-live line reports progress ("2 of 5 steps done"). Open steps are #0f172a on #ffffff (17.85:1), done steps #475569 on #ffffff (7.58:1) and the progress line #334155 on #ffffff (10.35:1).

Source (copy-ready)

<div class="dcl-ordered-checklist">
  <h2 class="dcl-ordered-checklist__heading" id="dcl-ordered-checklist-heading">Launch checklist</h2>
  <p class="dcl-ordered-checklist__progress" aria-live="polite">2 of 5 steps done</p>
  <ol class="dcl-ordered-checklist__list" aria-labelledby="dcl-ordered-checklist-heading">
    <li class="dcl-ordered-checklist__item dcl-ordered-checklist__item--done"><input type="checkbox" id="dcl-ordered-checklist-1" class="dcl-ordered-checklist__box" checked><label for="dcl-ordered-checklist-1" class="dcl-ordered-checklist__label"><span class="dcl-ordered-checklist__text">Freeze the release branch</span><span class="dcl-ordered-checklist__done"> (done)</span></label></li>
    <li class="dcl-ordered-checklist__item dcl-ordered-checklist__item--done"><input type="checkbox" id="dcl-ordered-checklist-2" class="dcl-ordered-checklist__box" checked><label for="dcl-ordered-checklist-2" class="dcl-ordered-checklist__label"><span class="dcl-ordered-checklist__text">Run the full test suite</span><span class="dcl-ordered-checklist__done"> (done)</span></label></li>
    <li class="dcl-ordered-checklist__item"><input type="checkbox" id="dcl-ordered-checklist-3" class="dcl-ordered-checklist__box"><label for="dcl-ordered-checklist-3" class="dcl-ordered-checklist__label"><span class="dcl-ordered-checklist__text">Write the release notes</span><span class="dcl-ordered-checklist__done" hidden> (done)</span></label></li>
    <li class="dcl-ordered-checklist__item"><input type="checkbox" id="dcl-ordered-checklist-4" class="dcl-ordered-checklist__box"><label for="dcl-ordered-checklist-4" class="dcl-ordered-checklist__label"><span class="dcl-ordered-checklist__text">Deploy to staging and smoke test</span><span class="dcl-ordered-checklist__done" hidden> (done)</span></label></li>
    <li class="dcl-ordered-checklist__item"><input type="checkbox" id="dcl-ordered-checklist-5" class="dcl-ordered-checklist__box"><label for="dcl-ordered-checklist-5" class="dcl-ordered-checklist__label"><span class="dcl-ordered-checklist__text">Announce the release to the team</span><span class="dcl-ordered-checklist__done" hidden> (done)</span></label></li>
  </ol>
</div>
<style>
.dcl-ordered-checklist { max-width: 28rem; font: inherit; color: #0f172a; background-color: #ffffff; }
.dcl-ordered-checklist__heading { margin: 0 0 0.25rem; font-size: 1.15rem; color: #0f172a; background-color: #ffffff; }
.dcl-ordered-checklist__progress { margin: 0 0 0.5rem; font-size: 0.9rem; color: #334155; background-color: #ffffff; }
.dcl-ordered-checklist__list { margin: 0; padding-left: 1.75rem; }
.dcl-ordered-checklist__item { padding: 0.4rem 0; color: #0f172a; background-color: #ffffff; }
.dcl-ordered-checklist__label { display: inline; overflow-wrap: anywhere; cursor: pointer; }
.dcl-ordered-checklist__box { width: 1.05rem; height: 1.05rem; margin: 0 0.5rem 0 0; vertical-align: -0.15rem; accent-color: #1d4ed8; }
.dcl-ordered-checklist__box:focus-visible { outline: 2px solid #1d4ed8; outline-offset: 2px; }
.dcl-ordered-checklist__item--done .dcl-ordered-checklist__text { text-decoration: line-through; color: #475569; background-color: #ffffff; }
.dcl-ordered-checklist__done { color: #475569; background-color: #ffffff; }
</style>
<script>
(function () {
  document.querySelectorAll(".dcl-ordered-checklist").forEach(function (root) {
    if (root.dataset.dclBound) { return; }
    root.dataset.dclBound = "true";
    var progress = root.querySelector(".dcl-ordered-checklist__progress");
    var items = Array.prototype.slice.call(root.querySelectorAll(".dcl-ordered-checklist__item"));
    function update() {
      var done = 0;
      items.forEach(function (item) {
        var box = item.querySelector(".dcl-ordered-checklist__box");
        var marker = item.querySelector(".dcl-ordered-checklist__done");
        var checked = !!(box && box.checked);
        if (checked) { done += 1; }
        item.classList.toggle("dcl-ordered-checklist__item--done", checked);
        if (marker) { marker.hidden = !checked; }
      });
      if (progress) { progress.textContent = done + " of " + items.length + " steps done"; }
    }
    items.forEach(function (item) {
      var box = item.querySelector(".dcl-ordered-checklist__box");
      if (box) { box.addEventListener("change", update); }
    });
    update();
  });
})();
</script>

Was this useful? Send feedback.