ARTLUNG LAB Share

Created Jun 2025

Kanban Task Board in CSS Grid

Demonstration of display: grid coupled with grid-auto-flow: column;

How does this work?

See also Kanban Task Board in CSS Grid (Part 2)

On Deck

In Progress

Done

One
Two
Three
Four
Five
Six
Seven
Eight
Nine
Ten

HTML

    <main class="task-board">
        <h2 class="on-deck">On Deck</h2>
        <h2 class="in-progress">In Progress</h2>
        <h2 class="done">Done</h2>
        <div>
            One
            <form>
                <label><input type="radio" name="task-1" value="on-deck" checked>On Deck</label>
                <label><input type="radio" name="task-1" value="in-progress">In Progress</label>
                <label><input type="radio" name="task-1" value="done">Done</label>
            </form>
        </div>
        <div>
            Two
            <form>
                <label><input type="radio" name="task-2" value="on-deck" checked>On Deck</label>
                <label><input type="radio" name="task-2" value="in-progress">In Progress</label>
                <label><input type="radio" name="task-2" value="done">Done</label>
            </form>
        </div>
        <div>
            Three
            <form>
                <label><input type="radio" name="task-3" value="on-deck" checked>On Deck</label>
                <label><input type="radio" name="task-3" value="in-progress">In Progress</label>
                <label><input type="radio" name="task-3" value="done">Done</label>
            </form>
        </div>
        <div>
            Four
            <form>
                <label><input type="radio" name="task-4" value="on-deck" checked>On Deck</label>
                <label><input type="radio" name="task-4" value="in-progress">In Progress</label>
                <label><input type="radio" name="task-4" value="done">Done</label>
            </form>
        </div>
        <div>
            Five
            <form>
                <label><input type="radio" name="task-5" value="on-deck" checked>On Deck</label>
                <label><input type="radio" name="task-5" value="in-progress">In Progress</label>
                <label><input type="radio" name="task-5" value="done">Done</label>
            </form>
        </div>
        <div>
            Six
            <form>
                <label><input type="radio" name="task-6" value="on-deck" checked>On Deck</label>
                <label><input type="radio" name="task-6" value="in-progress">In Progress</label>
                <label><input type="radio" name="task-6" value="done">Done</label>
            </form>
        </div>
        <div>
            Seven
            <form>
                <label><input type="radio" name="task-7" value="on-deck" checked>On Deck</label>
                <label><input type="radio" name="task-7" value="in-progress">In Progress</label>
                <label><input type="radio" name="task-7" value="done">Done</label>
            </form>
        </div>
        <div>
            Eight
            <form>
                <label><input type="radio" name="task-8" value="on-deck" checked>On Deck</label>
                <label><input type="radio" name="task-8" value="in-progress">In Progress</label>
                <label><input type="radio" name="task-8" value="done">Done</label>
            </form>
        </div>
        <div>
            Nine
            <form>
                <label><input type="radio" name="task-9" value="on-deck" checked>On Deck</label>
                <label><input type="radio" name="task-9" value="in-progress">In Progress</label>
                <label><input type="radio" name="task-9" value="done">Done</label>
            </form>
        </div>
        <div>
            Ten
            <form>
                <label><input type="radio" name="task-10" value="on-deck" checked>On Deck</label>
                <label><input type="radio" name="task-10" value="in-progress">In Progress</label>
                <label><input type="radio" name="task-10" value="done">Done</label>
            </form>
        </div>
    </main>

SCSS

:root {
  --color-on-deck: lightblue;
  --color-in-progress: lightgreen;
  --color-done: #ccc;
}
body {
  font-family: system-ui, sans-serif;
}
code {
  font-size: 1rem;
}
main.task-board {
  display: grid;
  gap: 1.2rem;
  padding: 0.5rem;
  grid-template-columns: 1fr;
  & > form {
  }
  h2 {
    display: none;
  }

  div {
    --color: var(--color-done);
    border: 1px solid oklch(from var(--color) 0.7 c h);
    border-radius: 0.5em;
    background: var(--color);
    padding: 1rem;
    --color: var(--color-on-deck);
    &:has(input[value="on-deck"]:checked) {
    }
    &:has(input[value="in-progress"]:checked) {
      --color: var(--color-in-progress);
    }
    &:has(input[value="done"]:checked) {
      --color: var(--color-done);
    }


    form {
      margin: 1rem 0 0 auto;
      opacity: 0.8;
      display: flex;
      gap: 0;
      border: 1px solid oklch(from var(--color) 0.7 c h);
      border-radius: 0.2rem;
      width: min-content;
      label {
        cursor: pointer;
        font-size: small;
        white-space: nowrap;
        padding: 0.2rem 0.5rem;
        --actionColor: #0000;
        background: color-mix(in srgb, var(--actionColor), var(--color));
        &:has(input[value="on-deck"]) {
          --actionColor: var(--color-on-deck);
        }
        &:has(input[value="in-progress"]) {
          --actionColor: var(--color-in-progress);
        }
        &:has(input[value="done"]) {
          --actionColor: var(--color-done);
        }
        &:has(input:checked) {
          opacity: 0.5;
        }
        input {
          display: none;
        }
      }
    }
  }
}
@media only screen and (min-width: 800px) {
  main.task-board {
    grid-template-columns: 1fr 1fr 1fr;
    grid-auto-flow: column;
    background: linear-gradient(
                    90deg,
                    color-mix(in srgb, var(--color-on-deck),     #0000 60%) 33.333%,
                    color-mix(in srgb, var(--color-in-progress), #0000 60%) 0 66.667%,
                    color-mix(in srgb, var(--color-done),        #0000 60%) 0
    );

    h2 {
      display: block;
      margin: 0;
      border: solid;
      padding: 0 0 0.2ch;
      border-width: 0 0 0.2ch 0;
      &.on-deck {
        grid-column: 1;
      }
      &.in-progress {
        grid-column: 2;
      }
      &.done {
        grid-column: 3;
      }
    }
    div {
      grid-column: 1;
      &:has(input[value="on-deck"]:checked) {
        // already has default
      }
      &:has(input[value="in-progress"]:checked) {
        grid-column: 2;
      }
      &:has(input[value="done"]:checked) {
        grid-column: 3;
      }
      form {
        label {
          width: 100%;
        }
      }
    }
  }
}

Shoutout

...to carrvo over on the indieweb for inspiring my investigation of this layout.