Kanban Board
Three-column kanban — Todo / In Progress / Done — with each column scrolling independently. Cards stack with `grid-auto-rows: min-content` so columns of different lengths still align at the top.
The code
<div class="gl-kb">
<section class="gl-kb-col gl-kb-todo">
<header><strong>To-do</strong><span class="gl-kb-coord">column 1</span></header>
<article>Sketch onboarding</article>
<article>Brand audit</article>
<article>Set up CI</article>
</section>
<section class="gl-kb-col gl-kb-prog">
<header><strong>In progress</strong><span class="gl-kb-coord">column 2</span></header>
<article>Refactor auth</article>
<article>Email templates</article>
</section>
<section class="gl-kb-col gl-kb-done">
<header><strong>Done</strong><span class="gl-kb-coord">column 3</span></header>
<article>Spec sign-off</article>
<article>Vendor selected</article>
<article>Wire-frames</article>
<article>Kick-off call</article>
</section>
</div> <div class="gl-kb">
<section class="gl-kb-col gl-kb-todo">
<header><strong>To-do</strong><span class="gl-kb-coord">column 1</span></header>
<article>Sketch onboarding</article>
<article>Brand audit</article>
<article>Set up CI</article>
</section>
<section class="gl-kb-col gl-kb-prog">
<header><strong>In progress</strong><span class="gl-kb-coord">column 2</span></header>
<article>Refactor auth</article>
<article>Email templates</article>
</section>
<section class="gl-kb-col gl-kb-done">
<header><strong>Done</strong><span class="gl-kb-coord">column 3</span></header>
<article>Spec sign-off</article>
<article>Vendor selected</article>
<article>Wire-frames</article>
<article>Kick-off call</article>
</section>
</div>.gl-kb {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
width: 100%;
min-height: 480px;
padding: 18px;
background: #0f172a;
font-family: 'Inter', system-ui, sans-serif;
color: #e2e8f0;
box-sizing: border-box;
align-items: start;
}
.gl-kb-col {
background: #1e293b;
border: 1px solid rgba(148,163,184,0.18);
border-radius: 14px;
padding: 14px;
display: grid;
grid-auto-rows: min-content;
gap: 8px;
}
.gl-kb-col header {
display: flex; align-items: center; justify-content: space-between;
padding: 6px 10px;
border-radius: 8px;
margin-bottom: 4px;
}
.gl-kb-col header strong { font-size: 13px; font-weight: 700; }
.gl-kb-coord {
font-family: 'JetBrains Mono', monospace;
font-size: 10px; letter-spacing: 0.04em;
padding: 2px 8px; border-radius: 999px;
}
.gl-kb-todo header { background: rgba(148,163,184,0.18); color: #cbd5e1; }
.gl-kb-todo .gl-kb-coord { background: rgba(15,23,42,0.5); color: #94a3b8; }
.gl-kb-prog header { background: rgba(245,158,11,0.18); color: #fbbf24; }
.gl-kb-prog .gl-kb-coord { background: rgba(15,23,42,0.5); color: #fbbf24; }
.gl-kb-done header { background: rgba(34,197,94,0.18); color: #34d399; }
.gl-kb-done .gl-kb-coord { background: rgba(15,23,42,0.5); color: #34d399; }
.gl-kb-col article {
background: #334155;
border: 1px solid rgba(148,163,184,0.18);
border-left: 3px solid currentColor;
border-radius: 8px;
padding: 10px 12px;
font-size: 13px;
color: #e2e8f0;
}
.gl-kb-todo article { color: #94a3b8; }
.gl-kb-prog article { color: #fbbf24; }
.gl-kb-done article { color: #34d399; }
.gl-kb-col article { color: #e2e8f0; }
.gl-kb-todo article { border-left-color: #94a3b8; }
.gl-kb-prog article { border-left-color: #fbbf24; }
.gl-kb-done article { border-left-color: #34d399; }
@media (max-width: 720px) {
.gl-kb { grid-template-columns: 1fr; }
} .gl-kb {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
width: 100%;
min-height: 480px;
padding: 18px;
background: #0f172a;
font-family: 'Inter', system-ui, sans-serif;
color: #e2e8f0;
box-sizing: border-box;
align-items: start;
}
.gl-kb-col {
background: #1e293b;
border: 1px solid rgba(148,163,184,0.18);
border-radius: 14px;
padding: 14px;
display: grid;
grid-auto-rows: min-content;
gap: 8px;
}
.gl-kb-col header {
display: flex; align-items: center; justify-content: space-between;
padding: 6px 10px;
border-radius: 8px;
margin-bottom: 4px;
}
.gl-kb-col header strong { font-size: 13px; font-weight: 700; }
.gl-kb-coord {
font-family: 'JetBrains Mono', monospace;
font-size: 10px; letter-spacing: 0.04em;
padding: 2px 8px; border-radius: 999px;
}
.gl-kb-todo header { background: rgba(148,163,184,0.18); color: #cbd5e1; }
.gl-kb-todo .gl-kb-coord { background: rgba(15,23,42,0.5); color: #94a3b8; }
.gl-kb-prog header { background: rgba(245,158,11,0.18); color: #fbbf24; }
.gl-kb-prog .gl-kb-coord { background: rgba(15,23,42,0.5); color: #fbbf24; }
.gl-kb-done header { background: rgba(34,197,94,0.18); color: #34d399; }
.gl-kb-done .gl-kb-coord { background: rgba(15,23,42,0.5); color: #34d399; }
.gl-kb-col article {
background: #334155;
border: 1px solid rgba(148,163,184,0.18);
border-left: 3px solid currentColor;
border-radius: 8px;
padding: 10px 12px;
font-size: 13px;
color: #e2e8f0;
}
.gl-kb-todo article { color: #94a3b8; }
.gl-kb-prog article { color: #fbbf24; }
.gl-kb-done article { color: #34d399; }
.gl-kb-col article { color: #e2e8f0; }
.gl-kb-todo article { border-left-color: #94a3b8; }
.gl-kb-prog article { border-left-color: #fbbf24; }
.gl-kb-done article { border-left-color: #34d399; }
@media (max-width: 720px) {
.gl-kb { grid-template-columns: 1fr; }
}