17 CSS Dashboard Layouts12 / 17
Minimalist Vanilla CSS Dashboard Shell (Zero Dependencies)
Forty-five lines of commented CSS. Zero JavaScript, zero classes-per-pixel utility soup, zero build step — a complete dashboard shell styled almost entirely through semantic landmarks (header, nav, main, aside, footer) so it drops straight into server-rendered PHP, Django or Rails templates. The CSS is the tutorial: every line carries a comment saying what it earns. Delete the comments and it fits in a tweet thread.
Published
The code
<section class="cdl-12" aria-label="Vanilla zero-dependency shell demo">
<div class="cdl-12__shell">
<header><strong>Plainboard</strong><a href="#docs">Docs</a><a href="#account">Account</a></header>
<nav aria-label="Primary">
<a href="#home" aria-current="page">Home</a>
<a href="#projects">Projects</a>
<a href="#tasks">Tasks</a>
<a href="#invoices">Invoices</a>
<a href="#team">Team</a>
</nav>
<main>
<h1>Home</h1>
<div class="cdl-12__stats">
<section><h2>Open tasks</h2><p>23</p></section>
<section><h2>Due this week</h2><p>7</p></section>
<section><h2>Hours logged</h2><p>31.5</p></section>
</div>
<section>
<h2>Recent activity</h2>
<ul>
<li>Invoice <b>#204</b> sent to Harper & Co <time>10:41</time></li>
<li>Task <b>“Migrate DNS”</b> completed <time>09:12</time></li>
<li>New project <b>Riverside</b> created <time>Yesterday</time></li>
<li>Task <b>“QA pass”</b> assigned to Sam <time>Yesterday</time></li>
</ul>
</section>
</main>
<footer>Rendered server-side · no client framework · <a href="#src">view source</a></footer>
</div>
</section><section class="cdl-12" aria-label="Vanilla zero-dependency shell demo">
<div class="cdl-12__shell">
<header><strong>Plainboard</strong><a href="#docs">Docs</a><a href="#account">Account</a></header>
<nav aria-label="Primary">
<a href="#home" aria-current="page">Home</a>
<a href="#projects">Projects</a>
<a href="#tasks">Tasks</a>
<a href="#invoices">Invoices</a>
<a href="#team">Team</a>
</nav>
<main>
<h1>Home</h1>
<div class="cdl-12__stats">
<section><h2>Open tasks</h2><p>23</p></section>
<section><h2>Due this week</h2><p>7</p></section>
<section><h2>Hours logged</h2><p>31.5</p></section>
</div>
<section>
<h2>Recent activity</h2>
<ul>
<li>Invoice <b>#204</b> sent to Harper & Co <time>10:41</time></li>
<li>Task <b>“Migrate DNS”</b> completed <time>09:12</time></li>
<li>New project <b>Riverside</b> created <time>Yesterday</time></li>
<li>Task <b>“QA pass”</b> assigned to Sam <time>Yesterday</time></li>
</ul>
</section>
</main>
<footer>Rendered server-side · no client framework · <a href="#src">view source</a></footer>
</div>
</section>.cdl-12,
.cdl-12 *,
.cdl-12 *::before,
.cdl-12 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cdl-12 {
background: var(--bg);
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
--accent: oklch(0.55 0.15 250);
--ink: oklch(0.27 0.01 250);
--mut: oklch(0.52 0.015 250);
--edge: oklch(0.9 0.008 250);
--paper: oklch(0.985 0.003 250);
--pad: 14px;
font-family: system-ui,sans-serif;
color: var(--ink);
container-type: inline-size;
}
/* ——— the ~45-line shell starts here ——— */
.cdl-12 .cdl-12__shell {
width: 100%;
height: 100vh;
display: grid;
grid-template-columns: 220px minmax(0,1fr);
grid-template-rows: auto minmax(0,1fr) auto;
grid-template-areas: "header header" "nav main" "footer footer";
border: 1px solid var(--edge);
border-radius: 14px;
overflow: hidden;
background: var(--paper);
}
.cdl-12 .cdl-12__shell>header {
grid-area: header;
display: flex;
align-items: center;
gap: 16px;
padding: var(--pad);
background: white;
border-bottom: 1px solid var(--edge);
}
.cdl-12 .cdl-12__shell>header strong {
margin-right: auto;
font-size: 15px;
}
.cdl-12 .cdl-12__shell>nav {
grid-area: nav;
display: flex;
flex-direction: column;
gap: 2px;
padding: var(--pad);
border-right: 1px solid var(--edge);
background: white;
}
.cdl-12 .cdl-12__shell>main {
grid-area: main;
overflow-y: auto;
overscroll-behavior: contain;
padding: calc(var(--pad)*1.3);
display: grid;
gap: var(--pad);
align-content: start;
}
.cdl-12 .cdl-12__shell>footer {
grid-area: footer;
padding: 10px var(--pad);
font-size: 11.5px;
color: var(--mut);
background: white;
border-top: 1px solid var(--edge);
}
.cdl-12 .cdl-12__shell a {
color: var(--accent);
text-decoration: none;
font-size: 13px;
font-weight: 550;
}
.cdl-12 .cdl-12__shell a:hover {
text-decoration: underline;
text-underline-offset: 3px;
}
.cdl-12 .cdl-12__shell a:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
border-radius: 3px;
}
.cdl-12 .cdl-12__shell>nav a {
color: var(--mut);
padding: 9px 12px;
border-radius: 8px;
}
.cdl-12 .cdl-12__shell>nav a:hover {
background: color-mix(in oklch,var(--accent) 6%,white);
color: var(--ink);
text-decoration: none;
}
.cdl-12 .cdl-12__shell>nav a[aria-current=page] {
background: color-mix(in oklch,var(--accent) 12%,white);
color: color-mix(in oklch,var(--accent) 75%,black);
}
.cdl-12 .cdl-12__shell h1 {
font-size: 18px;
letter-spacing: -.01em;
}
.cdl-12 .cdl-12__shell main section {
background: white;
border: 1px solid var(--edge);
border-radius: 11px;
padding: var(--pad);
}
.cdl-12 .cdl-12__shell main h2 {
font-size: 11px;
font-weight: 650;
letter-spacing: .09em;
text-transform: uppercase;
color: var(--mut);
margin-bottom: 6px;
}
.cdl-12__stats {
display: grid;
gap: var(--pad);
grid-template-columns: repeat(auto-fit,minmax(min(150px,100%),1fr));
}
.cdl-12__stats p {
font-size: 24px;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.cdl-12 .cdl-12__shell ul {
list-style: none;
display: grid;
gap: 1px;
}
.cdl-12 .cdl-12__shell li {
display: flex;
gap: 6px;
align-items: baseline;
font-size: 13px;
padding: 9px 2px;
border-bottom: 1px solid color-mix(in oklch,var(--edge) 55%,transparent);
}
.cdl-12 .cdl-12__shell li:last-child {
border-bottom: none;
}
.cdl-12 .cdl-12__shell li b {
font-weight: 600;
}
.cdl-12 .cdl-12__shell li time {
margin-left: auto;
font-size: 11px;
color: var(--mut);
font-variant-numeric: tabular-nums;
}
@container (max-width: 620px) {
.cdl-12 .cdl-12__shell {
grid-template-columns: minmax(0,1fr);
grid-template-areas: "header" "nav" "main" "footer";
grid-template-rows: auto auto minmax(0,1fr) auto;
}
.cdl-12 .cdl-12__shell>nav {
flex-direction: row;
overflow-x: auto;
border-right: none;
border-bottom: 1px solid var(--edge);
}
}
/* ——— shell ends ——— */.cdl-12,
.cdl-12 *,
.cdl-12 *::before,
.cdl-12 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cdl-12 {
background: var(--bg);
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
--accent: oklch(0.55 0.15 250);
--ink: oklch(0.27 0.01 250);
--mut: oklch(0.52 0.015 250);
--edge: oklch(0.9 0.008 250);
--paper: oklch(0.985 0.003 250);
--pad: 14px;
font-family: system-ui,sans-serif;
color: var(--ink);
container-type: inline-size;
}
/* ——— the ~45-line shell starts here ——— */
.cdl-12 .cdl-12__shell {
width: 100%;
height: 100vh;
display: grid;
grid-template-columns: 220px minmax(0,1fr);
grid-template-rows: auto minmax(0,1fr) auto;
grid-template-areas: "header header" "nav main" "footer footer";
border: 1px solid var(--edge);
border-radius: 14px;
overflow: hidden;
background: var(--paper);
}
.cdl-12 .cdl-12__shell>header {
grid-area: header;
display: flex;
align-items: center;
gap: 16px;
padding: var(--pad);
background: white;
border-bottom: 1px solid var(--edge);
}
.cdl-12 .cdl-12__shell>header strong {
margin-right: auto;
font-size: 15px;
}
.cdl-12 .cdl-12__shell>nav {
grid-area: nav;
display: flex;
flex-direction: column;
gap: 2px;
padding: var(--pad);
border-right: 1px solid var(--edge);
background: white;
}
.cdl-12 .cdl-12__shell>main {
grid-area: main;
overflow-y: auto;
overscroll-behavior: contain;
padding: calc(var(--pad)*1.3);
display: grid;
gap: var(--pad);
align-content: start;
}
.cdl-12 .cdl-12__shell>footer {
grid-area: footer;
padding: 10px var(--pad);
font-size: 11.5px;
color: var(--mut);
background: white;
border-top: 1px solid var(--edge);
}
.cdl-12 .cdl-12__shell a {
color: var(--accent);
text-decoration: none;
font-size: 13px;
font-weight: 550;
}
.cdl-12 .cdl-12__shell a:hover {
text-decoration: underline;
text-underline-offset: 3px;
}
.cdl-12 .cdl-12__shell a:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
border-radius: 3px;
}
.cdl-12 .cdl-12__shell>nav a {
color: var(--mut);
padding: 9px 12px;
border-radius: 8px;
}
.cdl-12 .cdl-12__shell>nav a:hover {
background: color-mix(in oklch,var(--accent) 6%,white);
color: var(--ink);
text-decoration: none;
}
.cdl-12 .cdl-12__shell>nav a[aria-current=page] {
background: color-mix(in oklch,var(--accent) 12%,white);
color: color-mix(in oklch,var(--accent) 75%,black);
}
.cdl-12 .cdl-12__shell h1 {
font-size: 18px;
letter-spacing: -.01em;
}
.cdl-12 .cdl-12__shell main section {
background: white;
border: 1px solid var(--edge);
border-radius: 11px;
padding: var(--pad);
}
.cdl-12 .cdl-12__shell main h2 {
font-size: 11px;
font-weight: 650;
letter-spacing: .09em;
text-transform: uppercase;
color: var(--mut);
margin-bottom: 6px;
}
.cdl-12__stats {
display: grid;
gap: var(--pad);
grid-template-columns: repeat(auto-fit,minmax(min(150px,100%),1fr));
}
.cdl-12__stats p {
font-size: 24px;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.cdl-12 .cdl-12__shell ul {
list-style: none;
display: grid;
gap: 1px;
}
.cdl-12 .cdl-12__shell li {
display: flex;
gap: 6px;
align-items: baseline;
font-size: 13px;
padding: 9px 2px;
border-bottom: 1px solid color-mix(in oklch,var(--edge) 55%,transparent);
}
.cdl-12 .cdl-12__shell li:last-child {
border-bottom: none;
}
.cdl-12 .cdl-12__shell li b {
font-weight: 600;
}
.cdl-12 .cdl-12__shell li time {
margin-left: auto;
font-size: 11px;
color: var(--mut);
font-variant-numeric: tabular-nums;
}
@container (max-width: 620px) {
.cdl-12 .cdl-12__shell {
grid-template-columns: minmax(0,1fr);
grid-template-areas: "header" "nav" "main" "footer";
grid-template-rows: auto auto minmax(0,1fr) auto;
}
.cdl-12 .cdl-12__shell>nav {
flex-direction: row;
overflow-x: auto;
border-right: none;
border-bottom: 1px solid var(--edge);
}
}
/* ——— shell ends ——— */Here's a working CSS Dashboard Layout from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Minimalist Vanilla CSS Dashboard Shell (Zero Dependencies)
Source: https://codefronts.com/layouts/css-dashboard-layouts/minimalist-vanilla-css-dashboard-shell-zero-dependencies/
Forty-five lines of commented CSS. Zero JavaScript, zero classes-per-pixel utility soup, zero build step — a complete dashboard shell styled almost entirely through semantic landmarks (header, nav, main, aside, footer) so it drops straight into server-rendered PHP, Django or Rails templates. The CSS is the tutorial: every line carries a comment saying what it earns. Delete the comments and it fits in a tweet thread.
## HTML
```html
<section class="cdl-12" aria-label="Vanilla zero-dependency shell demo">
<div class="cdl-12__shell">
<header><strong>Plainboard</strong><a href="#docs">Docs</a><a href="#account">Account</a></header>
<nav aria-label="Primary">
<a href="#home" aria-current="page">Home</a>
<a href="#projects">Projects</a>
<a href="#tasks">Tasks</a>
<a href="#invoices">Invoices</a>
<a href="#team">Team</a>
</nav>
<main>
<h1>Home</h1>
<div class="cdl-12__stats">
<section><h2>Open tasks</h2><p>23</p></section>
<section><h2>Due this week</h2><p>7</p></section>
<section><h2>Hours logged</h2><p>31.5</p></section>
</div>
<section>
<h2>Recent activity</h2>
<ul>
<li>Invoice <b>#204</b> sent to Harper & Co <time>10:41</time></li>
<li>Task <b>“Migrate DNS”</b> completed <time>09:12</time></li>
<li>New project <b>Riverside</b> created <time>Yesterday</time></li>
<li>Task <b>“QA pass”</b> assigned to Sam <time>Yesterday</time></li>
</ul>
</section>
</main>
<footer>Rendered server-side · no client framework · <a href="#src">view source</a></footer>
</div>
</section>
```
## CSS
```css
.cdl-12,
.cdl-12 *,
.cdl-12 *::before,
.cdl-12 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cdl-12 {
background: var(--bg);
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
--accent: oklch(0.55 0.15 250);
--ink: oklch(0.27 0.01 250);
--mut: oklch(0.52 0.015 250);
--edge: oklch(0.9 0.008 250);
--paper: oklch(0.985 0.003 250);
--pad: 14px;
font-family: system-ui,sans-serif;
color: var(--ink);
container-type: inline-size;
}
/* ——— the ~45-line shell starts here ——— */
.cdl-12 .cdl-12__shell {
width: 100%;
height: 100vh;
display: grid;
grid-template-columns: 220px minmax(0,1fr);
grid-template-rows: auto minmax(0,1fr) auto;
grid-template-areas: "header header" "nav main" "footer footer";
border: 1px solid var(--edge);
border-radius: 14px;
overflow: hidden;
background: var(--paper);
}
.cdl-12 .cdl-12__shell>header {
grid-area: header;
display: flex;
align-items: center;
gap: 16px;
padding: var(--pad);
background: white;
border-bottom: 1px solid var(--edge);
}
.cdl-12 .cdl-12__shell>header strong {
margin-right: auto;
font-size: 15px;
}
.cdl-12 .cdl-12__shell>nav {
grid-area: nav;
display: flex;
flex-direction: column;
gap: 2px;
padding: var(--pad);
border-right: 1px solid var(--edge);
background: white;
}
.cdl-12 .cdl-12__shell>main {
grid-area: main;
overflow-y: auto;
overscroll-behavior: contain;
padding: calc(var(--pad)*1.3);
display: grid;
gap: var(--pad);
align-content: start;
}
.cdl-12 .cdl-12__shell>footer {
grid-area: footer;
padding: 10px var(--pad);
font-size: 11.5px;
color: var(--mut);
background: white;
border-top: 1px solid var(--edge);
}
.cdl-12 .cdl-12__shell a {
color: var(--accent);
text-decoration: none;
font-size: 13px;
font-weight: 550;
}
.cdl-12 .cdl-12__shell a:hover {
text-decoration: underline;
text-underline-offset: 3px;
}
.cdl-12 .cdl-12__shell a:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
border-radius: 3px;
}
.cdl-12 .cdl-12__shell>nav a {
color: var(--mut);
padding: 9px 12px;
border-radius: 8px;
}
.cdl-12 .cdl-12__shell>nav a:hover {
background: color-mix(in oklch,var(--accent) 6%,white);
color: var(--ink);
text-decoration: none;
}
.cdl-12 .cdl-12__shell>nav a[aria-current=page] {
background: color-mix(in oklch,var(--accent) 12%,white);
color: color-mix(in oklch,var(--accent) 75%,black);
}
.cdl-12 .cdl-12__shell h1 {
font-size: 18px;
letter-spacing: -.01em;
}
.cdl-12 .cdl-12__shell main section {
background: white;
border: 1px solid var(--edge);
border-radius: 11px;
padding: var(--pad);
}
.cdl-12 .cdl-12__shell main h2 {
font-size: 11px;
font-weight: 650;
letter-spacing: .09em;
text-transform: uppercase;
color: var(--mut);
margin-bottom: 6px;
}
.cdl-12__stats {
display: grid;
gap: var(--pad);
grid-template-columns: repeat(auto-fit,minmax(min(150px,100%),1fr));
}
.cdl-12__stats p {
font-size: 24px;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.cdl-12 .cdl-12__shell ul {
list-style: none;
display: grid;
gap: 1px;
}
.cdl-12 .cdl-12__shell li {
display: flex;
gap: 6px;
align-items: baseline;
font-size: 13px;
padding: 9px 2px;
border-bottom: 1px solid color-mix(in oklch,var(--edge) 55%,transparent);
}
.cdl-12 .cdl-12__shell li:last-child {
border-bottom: none;
}
.cdl-12 .cdl-12__shell li b {
font-weight: 600;
}
.cdl-12 .cdl-12__shell li time {
margin-left: auto;
font-size: 11px;
color: var(--mut);
font-variant-numeric: tabular-nums;
}
@container (max-width: 620px) {
.cdl-12 .cdl-12__shell {
grid-template-columns: minmax(0,1fr);
grid-template-areas: "header" "nav" "main" "footer";
grid-template-rows: auto auto minmax(0,1fr) auto;
}
.cdl-12 .cdl-12__shell>nav {
flex-direction: row;
overflow-x: auto;
border-right: none;
border-bottom: 1px solid var(--edge);
}
}
/* ——— shell ends ——— */
```Here's a working CSS Dashboard Layout from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Minimalist Vanilla CSS Dashboard Shell (Zero Dependencies)
Source: https://codefronts.com/layouts/css-dashboard-layouts/minimalist-vanilla-css-dashboard-shell-zero-dependencies/
Forty-five lines of commented CSS. Zero JavaScript, zero classes-per-pixel utility soup, zero build step — a complete dashboard shell styled almost entirely through semantic landmarks (header, nav, main, aside, footer) so it drops straight into server-rendered PHP, Django or Rails templates. The CSS is the tutorial: every line carries a comment saying what it earns. Delete the comments and it fits in a tweet thread.
## HTML
```html
<section class="cdl-12" aria-label="Vanilla zero-dependency shell demo">
<div class="cdl-12__shell">
<header><strong>Plainboard</strong><a href="#docs">Docs</a><a href="#account">Account</a></header>
<nav aria-label="Primary">
<a href="#home" aria-current="page">Home</a>
<a href="#projects">Projects</a>
<a href="#tasks">Tasks</a>
<a href="#invoices">Invoices</a>
<a href="#team">Team</a>
</nav>
<main>
<h1>Home</h1>
<div class="cdl-12__stats">
<section><h2>Open tasks</h2><p>23</p></section>
<section><h2>Due this week</h2><p>7</p></section>
<section><h2>Hours logged</h2><p>31.5</p></section>
</div>
<section>
<h2>Recent activity</h2>
<ul>
<li>Invoice <b>#204</b> sent to Harper & Co <time>10:41</time></li>
<li>Task <b>“Migrate DNS”</b> completed <time>09:12</time></li>
<li>New project <b>Riverside</b> created <time>Yesterday</time></li>
<li>Task <b>“QA pass”</b> assigned to Sam <time>Yesterday</time></li>
</ul>
</section>
</main>
<footer>Rendered server-side · no client framework · <a href="#src">view source</a></footer>
</div>
</section>
```
## CSS
```css
.cdl-12,
.cdl-12 *,
.cdl-12 *::before,
.cdl-12 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.cdl-12 {
background: var(--bg);
width: 100%;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
--accent: oklch(0.55 0.15 250);
--ink: oklch(0.27 0.01 250);
--mut: oklch(0.52 0.015 250);
--edge: oklch(0.9 0.008 250);
--paper: oklch(0.985 0.003 250);
--pad: 14px;
font-family: system-ui,sans-serif;
color: var(--ink);
container-type: inline-size;
}
/* ——— the ~45-line shell starts here ——— */
.cdl-12 .cdl-12__shell {
width: 100%;
height: 100vh;
display: grid;
grid-template-columns: 220px minmax(0,1fr);
grid-template-rows: auto minmax(0,1fr) auto;
grid-template-areas: "header header" "nav main" "footer footer";
border: 1px solid var(--edge);
border-radius: 14px;
overflow: hidden;
background: var(--paper);
}
.cdl-12 .cdl-12__shell>header {
grid-area: header;
display: flex;
align-items: center;
gap: 16px;
padding: var(--pad);
background: white;
border-bottom: 1px solid var(--edge);
}
.cdl-12 .cdl-12__shell>header strong {
margin-right: auto;
font-size: 15px;
}
.cdl-12 .cdl-12__shell>nav {
grid-area: nav;
display: flex;
flex-direction: column;
gap: 2px;
padding: var(--pad);
border-right: 1px solid var(--edge);
background: white;
}
.cdl-12 .cdl-12__shell>main {
grid-area: main;
overflow-y: auto;
overscroll-behavior: contain;
padding: calc(var(--pad)*1.3);
display: grid;
gap: var(--pad);
align-content: start;
}
.cdl-12 .cdl-12__shell>footer {
grid-area: footer;
padding: 10px var(--pad);
font-size: 11.5px;
color: var(--mut);
background: white;
border-top: 1px solid var(--edge);
}
.cdl-12 .cdl-12__shell a {
color: var(--accent);
text-decoration: none;
font-size: 13px;
font-weight: 550;
}
.cdl-12 .cdl-12__shell a:hover {
text-decoration: underline;
text-underline-offset: 3px;
}
.cdl-12 .cdl-12__shell a:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
border-radius: 3px;
}
.cdl-12 .cdl-12__shell>nav a {
color: var(--mut);
padding: 9px 12px;
border-radius: 8px;
}
.cdl-12 .cdl-12__shell>nav a:hover {
background: color-mix(in oklch,var(--accent) 6%,white);
color: var(--ink);
text-decoration: none;
}
.cdl-12 .cdl-12__shell>nav a[aria-current=page] {
background: color-mix(in oklch,var(--accent) 12%,white);
color: color-mix(in oklch,var(--accent) 75%,black);
}
.cdl-12 .cdl-12__shell h1 {
font-size: 18px;
letter-spacing: -.01em;
}
.cdl-12 .cdl-12__shell main section {
background: white;
border: 1px solid var(--edge);
border-radius: 11px;
padding: var(--pad);
}
.cdl-12 .cdl-12__shell main h2 {
font-size: 11px;
font-weight: 650;
letter-spacing: .09em;
text-transform: uppercase;
color: var(--mut);
margin-bottom: 6px;
}
.cdl-12__stats {
display: grid;
gap: var(--pad);
grid-template-columns: repeat(auto-fit,minmax(min(150px,100%),1fr));
}
.cdl-12__stats p {
font-size: 24px;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.cdl-12 .cdl-12__shell ul {
list-style: none;
display: grid;
gap: 1px;
}
.cdl-12 .cdl-12__shell li {
display: flex;
gap: 6px;
align-items: baseline;
font-size: 13px;
padding: 9px 2px;
border-bottom: 1px solid color-mix(in oklch,var(--edge) 55%,transparent);
}
.cdl-12 .cdl-12__shell li:last-child {
border-bottom: none;
}
.cdl-12 .cdl-12__shell li b {
font-weight: 600;
}
.cdl-12 .cdl-12__shell li time {
margin-left: auto;
font-size: 11px;
color: var(--mut);
font-variant-numeric: tabular-nums;
}
@container (max-width: 620px) {
.cdl-12 .cdl-12__shell {
grid-template-columns: minmax(0,1fr);
grid-template-areas: "header" "nav" "main" "footer";
grid-template-rows: auto auto minmax(0,1fr) auto;
}
.cdl-12 .cdl-12__shell>nav {
flex-direction: row;
overflow-x: auto;
border-right: none;
border-bottom: 1px solid var(--edge);
}
}
/* ——— shell ends ——— */
```How this works
The shell styles ELEMENTS, not classes — your backend templates stay clean:
/* 1 · the frame: three rows, two columns, one gap */
.shell{
display:grid; height:100%;
grid-template-columns: 220px minmax(0,1fr);
grid-template-rows: auto minmax(0,1fr) auto;
grid-template-areas: 'header header' 'nav main' 'footer footer';
}
/* 2 · landmarks claim their areas — no wrapper divs */
.shell > header{ grid-area:header; }
.shell > nav { grid-area:nav; }
.shell > main { grid-area:main; overflow-y:auto; }
.shell > footer{ grid-area:footer; }Everything else is a short system: one --accent and four neutrals derived from color-mix(); cards that are just main > section; an auto-fit stat row; aria-current=page doubling as the active-link style hook (state lives in the markup you already render server-side):
nav a[aria-current=page]{
background:color-mix(in oklch, var(--accent) 12%, white);
}Because the selectors are landmark-based, the accessibility story is enforced by construction — you literally cannot use the stylesheet without semantic HTML. The one media-free responsive move: the stat grid uses auto-fit/minmax, and the shell collapses to a single column under 620px of container width in three extra lines.
Make it yours
- Re-brand in one line:
--accentfeeds every tint via color-mix — links, active states, focus rings. - Density:
--pad(14px) spaces the whole shell; 10px turns it into a compact ops tool. - Swap the nav column for a top tab row by re-drawing
grid-template-areas— see demo 06; the landmarks don't change. - Add dark mode by pairing this with demo 10's token block — the landmark selectors are already token-driven.
Gotchas — read before shipping
- Element selectors are global by nature — the shell scopes everything under
.cdl-12 .shellhere (and you should scope underbody.dashboardor similar) so a marketing page's<aside>doesn't inherit dashboard styling. aria-current=pageis the correct semantic for “you are here” — resist inventing an.activeclass; assistive tech announces the ARIA version for free.- Zero-JS means no client-side drawer: on narrow containers the nav collapses to a horizontal scroll strip instead — an honest, dependency-free tradeoff (upgrade path: demo 07).
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.2+ | 113+ | 111+ |
Nothing here is newer than 2023: grid template areas (2017), auto-fit (2017), color-mix/oklch (the stated floor), container query for the collapse (Chrome 105 / Safari 16 / Firefox 110).