AI CSS Animations

Grocery List Scribble Checkbox

A handwritten shopping list: a rough pen tick fills the sketchy box and a wavy scribble crosses the item out. The scribble is an SVG revealed with clip-path, so it stretches to any word.

Also known as: shopping list checkbox css, cross out text animation css, hand drawn strikethrough.

Groceries

HTML

<div class="chk-grocery-list-scribble">
  <p class="chk-grocery-list-scribble-title">Groceries</p>
  <label class="chk-grocery-list-scribble-item">
    <input type="checkbox" checked>
    <svg class="chk-grocery-list-scribble-box" viewBox="0 0 24 24" aria-hidden="true"><path d="M4.6 5.3c4.9-.7 9.9-.6 14.8.2.5 4.5.4 9-.1 13.6-4.9.5-9.8.5-14.7-.1-.5-4.5-.5-9.1 0-13.7z"/><path class="chk-grocery-list-scribble-tick" d="M7.2 12.6c1.3 1 2.4 2.3 3.3 3.8 2-4.1 4.8-7.6 8.8-10.8"/></svg>
    <span class="chk-grocery-list-scribble-text">Eggs<svg class="chk-grocery-list-scribble-line" viewBox="0 0 100 20" preserveAspectRatio="none" aria-hidden="true"><path vector-effect="non-scaling-stroke" d="M1 13C10 5 20 17 32 9S55 4 68 12 88 15 99 8"/></svg></span>
  </label>
  <label class="chk-grocery-list-scribble-item">
    <input type="checkbox">
    <svg class="chk-grocery-list-scribble-box" viewBox="0 0 24 24" aria-hidden="true"><path d="M4.6 5.3c4.9-.7 9.9-.6 14.8.2.5 4.5.4 9-.1 13.6-4.9.5-9.8.5-14.7-.1-.5-4.5-.5-9.1 0-13.7z"/><path class="chk-grocery-list-scribble-tick" d="M7.2 12.6c1.3 1 2.4 2.3 3.3 3.8 2-4.1 4.8-7.6 8.8-10.8"/></svg>
    <span class="chk-grocery-list-scribble-text">Oat milk<svg class="chk-grocery-list-scribble-line" viewBox="0 0 100 20" preserveAspectRatio="none" aria-hidden="true"><path vector-effect="non-scaling-stroke" d="M1 13C10 5 20 17 32 9S55 4 68 12 88 15 99 8"/></svg></span>
  </label>
  <label class="chk-grocery-list-scribble-item">
    <input type="checkbox">
    <svg class="chk-grocery-list-scribble-box" viewBox="0 0 24 24" aria-hidden="true"><path d="M4.6 5.3c4.9-.7 9.9-.6 14.8.2.5 4.5.4 9-.1 13.6-4.9.5-9.8.5-14.7-.1-.5-4.5-.5-9.1 0-13.7z"/><path class="chk-grocery-list-scribble-tick" d="M7.2 12.6c1.3 1 2.4 2.3 3.3 3.8 2-4.1 4.8-7.6 8.8-10.8"/></svg>
    <span class="chk-grocery-list-scribble-text">Avocados<svg class="chk-grocery-list-scribble-line" viewBox="0 0 100 20" preserveAspectRatio="none" aria-hidden="true"><path vector-effect="non-scaling-stroke" d="M1 13C10 5 20 17 32 9S55 4 68 12 88 15 99 8"/></svg></span>
  </label>
</div>

CSS

.chk-grocery-list-scribble {
  --c: var(--chk-color, #3b82f6);
  font-size: var(--chk-size, 24px);
  display: grid;
  gap: 0.15em;
  padding: 0.7em 1.4em 0.8em 1.1em;
  border-radius: 0.5em;
  background: color-mix(in srgb, currentColor 5%, transparent);
  font-family: "Bradley Hand", "Segoe Print", "Comic Sans MS", "Marker Felt", cursive;
  line-height: 1.35;
  transform: rotate(-1.5deg);}
.chk-grocery-list-scribble-title {
  margin: 0 0 0.1em;
  font-size: 1.1em;
  font-weight: 700;
  color: var(--c);
}
.chk-grocery-list-scribble-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0.45em;
  font-size: 1.05em;
  cursor: pointer;
  -webkit-user-select: none;
  user-select: none;
}
.chk-grocery-list-scribble-item input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 1;
}
.chk-grocery-list-scribble-box {
  flex: none;
  width: 1.2em;
  height: 1.2em;
  overflow: visible;
  fill: none;
  stroke: color-mix(in srgb, currentColor 55%, transparent);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  border-radius: 0.2em;
}
.chk-grocery-list-scribble-tick {
  stroke: var(--c);
  stroke-width: 2.8;
  stroke-dasharray: 24;
  stroke-dashoffset: 24;
  transition: stroke-dashoffset 0.2s ease-in;
}
.chk-grocery-list-scribble-text {
  position: relative;
  transition: opacity 0.3s ease;
}
.chk-grocery-list-scribble-line {
  position: absolute;
  left: -0.2em;
  top: 20%;
  width: calc(100% + 0.4em);
  height: 60%;
  overflow: visible;
  fill: none;
  stroke: var(--c);
  stroke-width: 0.1em;
  stroke-linecap: round;
  clip-path: inset(0 100% 0 0);
  transition: clip-path 0.25s ease-in;
}
.chk-grocery-list-scribble-item input:checked + .chk-grocery-list-scribble-box .chk-grocery-list-scribble-tick {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 0.3s cubic-bezier(0.5, 0, 0.3, 1);
}
.chk-grocery-list-scribble-item input:checked ~ .chk-grocery-list-scribble-text {
  opacity: 0.55;
}
.chk-grocery-list-scribble-item input:checked ~ .chk-grocery-list-scribble-text .chk-grocery-list-scribble-line {
  clip-path: inset(0 -5% 0 0);
  transition: clip-path 0.45s cubic-bezier(0.6, 0, 0.3, 1) 0.2s;
}
.chk-grocery-list-scribble-item input:focus-visible + .chk-grocery-list-scribble-box {
  outline: 0.12em solid var(--c);
  outline-offset: 0.18em;
}

@media (prefers-reduced-motion: reduce) {
  .chk-grocery-list-scribble, .chk-grocery-list-scribble *, .chk-grocery-list-scribble::before, .chk-grocery-list-scribble::after, .chk-grocery-list-scribble *::before, .chk-grocery-list-scribble *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Customizing this snippet

  • Color: set --chk-color on the element or a parent. Currently previewing #3b82f6.
  • Size: set --chk-size. Every other dimension is in em, so the whole thing scales together. Currently previewing 24px.
  • Speed: change the duration on the transition or animation shorthand. Staggered delays are relative, so they keep their rhythm.
  • Reduced motion: the rule at the end of the CSS turns the motion off for people who asked their OS for less of it. Keep it.

Similar checkboxes