Skip to content

Instantly share code, notes, and snippets.

@McNull
Created August 29, 2026 09:51
Show Gist options
  • Select an option

  • Save McNull/e05f79ce1c205d880996210dbc1e4c19 to your computer and use it in GitHub Desktop.

Select an option

Save McNull/e05f79ce1c205d880996210dbc1e4c19 to your computer and use it in GitHub Desktop.
Compact picocss more suitable for dashboard
<!doctype html>
<html lang="en" data-theme="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="light dark">
<title>Pico Compact Pro — Component Preview</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
<style>
:root {
--pico-font-family-sans-serif: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--pico-font-size: 87.5%;
--pico-line-height: 1.35;
--pico-font-weight: 400;
--pico-spacing: 0.75rem;
--pico-form-element-spacing-vertical: 0.5rem;
--pico-form-element-spacing-horizontal: 0.75rem;
--pico-typography-spacing-vertical: 0.75rem;
--pico-block-spacing-vertical: 0.75rem;
--pico-block-spacing-horizontal: 0.875rem;
--pico-grid-column-gap: 0.75rem;
--pico-grid-row-gap: 0.75rem;
--pico-border-radius: 0.375rem;
--pico-border-width: 1px;
--pico-background-color: #fafafa;
--pico-color: #18181b;
--pico-muted-color: #71717a;
--pico-muted-border-color: #e4e4e7;
--pico-primary: #18181b;
--pico-primary-background: #18181b;
--pico-primary-border: #18181b;
--pico-primary-hover: #3f3f46;
--pico-primary-hover-background: #3f3f46;
--pico-primary-hover-border: #3f3f46;
--pico-primary-inverse: #fafafa;
--pico-secondary: #52525b;
--pico-secondary-background: #e4e4e7;
--pico-secondary-border: #e4e4e7;
--pico-secondary-hover-background: #d4d4d8;
--pico-secondary-hover-border: #d4d4d8;
--pico-secondary-inverse: #18181b;
--pico-contrast: #18181b;
--pico-contrast-background: #18181b;
--pico-contrast-border: #18181b;
--pico-contrast-inverse: #fafafa;
--pico-card-background-color: #ffffff;
--pico-card-border-color: #e4e4e7;
--pico-card-box-shadow: none;
--pico-form-element-background-color: #ffffff;
--pico-form-element-border-color: #d4d4d8;
--pico-form-element-color: #18181b;
--pico-form-element-placeholder-color: #a1a1aa;
--pico-form-element-active-background-color: #ffffff;
--pico-form-element-focus-color: rgba(24, 24, 27, 0.16);
--pico-code-background-color: #f4f4f5;
--pico-code-color: #3f3f46;
--pico-table-border-color: #e4e4e7;
--pico-progress-background-color: #e4e4e7;
--pico-progress-color: #18181b;
}
[data-theme="dark"] {
--pico-background-color: #09090b;
--pico-color: #fafafa;
--pico-muted-color: #a1a1aa;
--pico-muted-border-color: #27272a;
--pico-primary: #fafafa;
--pico-primary-background: #fafafa;
--pico-primary-border: #fafafa;
--pico-primary-hover: #e4e4e7;
--pico-primary-hover-background: #e4e4e7;
--pico-primary-hover-border: #e4e4e7;
--pico-primary-inverse: #09090b;
--pico-secondary: #d4d4d8;
--pico-secondary-background: #27272a;
--pico-secondary-border: #27272a;
--pico-secondary-hover-background: #3f3f46;
--pico-secondary-hover-border: #3f3f46;
--pico-secondary-inverse: #fafafa;
--pico-contrast: #fafafa;
--pico-contrast-background: #fafafa;
--pico-contrast-border: #fafafa;
--pico-contrast-inverse: #09090b;
--pico-card-background-color: #18181b;
--pico-card-border-color: #27272a;
--pico-card-box-shadow: none;
--pico-form-element-background-color: #18181b;
--pico-form-element-border-color: #3f3f46;
--pico-form-element-color: #fafafa;
--pico-form-element-placeholder-color: #71717a;
--pico-form-element-active-background-color: #18181b;
--pico-form-element-focus-color: rgba(250, 250, 250, 0.2);
--pico-code-background-color: #27272a;
--pico-code-color: #e4e4e7;
--pico-table-border-color: #27272a;
--pico-progress-background-color: #27272a;
--pico-progress-color: #fafafa;
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme]) {
--pico-background-color: #09090b;
--pico-color: #fafafa;
--pico-muted-color: #a1a1aa;
--pico-muted-border-color: #27272a;
--pico-primary: #fafafa;
--pico-primary-background: #fafafa;
--pico-primary-border: #fafafa;
--pico-primary-hover: #e4e4e7;
--pico-primary-hover-background: #e4e4e7;
--pico-primary-hover-border: #e4e4e7;
--pico-primary-inverse: #09090b;
--pico-secondary: #d4d4d8;
--pico-secondary-background: #27272a;
--pico-secondary-border: #27272a;
--pico-secondary-hover-background: #3f3f46;
--pico-secondary-hover-border: #3f3f46;
--pico-secondary-inverse: #fafafa;
--pico-contrast: #fafafa;
--pico-contrast-background: #fafafa;
--pico-contrast-border: #fafafa;
--pico-contrast-inverse: #09090b;
--pico-card-background-color: #18181b;
--pico-card-border-color: #27272a;
--pico-form-element-background-color: #18181b;
--pico-form-element-border-color: #3f3f46;
--pico-form-element-color: #fafafa;
--pico-form-element-placeholder-color: #71717a;
--pico-form-element-active-background-color: #18181b;
--pico-form-element-focus-color: rgba(250, 250, 250, 0.2);
--pico-code-background-color: #27272a;
--pico-code-color: #e4e4e7;
--pico-table-border-color: #27272a;
--pico-progress-background-color: #27272a;
--pico-progress-color: #fafafa;
}
}
@media (min-width: 576px), (min-width: 768px), (min-width: 1024px), (min-width: 1280px), (min-width: 1536px) {
:root { --pico-font-size: 87.5%; }
}
body { min-width: 320px; }
main.container { max-width: 1200px; padding-top: 1rem; padding-bottom: 2rem; }
h1, h2, h3, h4, h5, h6 { --pico-font-weight: 600; letter-spacing: -0.02em; }
h1 { --pico-font-size: 1.5rem; margin-bottom: 0.25rem; }
h2 { --pico-font-size: 1.125rem; }
h3 { --pico-font-size: 1rem; }
h4, h5, h6 { --pico-font-size: 0.875rem; }
article { border: 1px solid var(--pico-card-border-color); border-radius: 0.5rem; box-shadow: none; }
article > header, article > footer { padding: 0.75rem 0.875rem; background: transparent; border-color: var(--pico-card-border-color); }
article > header { margin-bottom: 0.75rem; }
article > footer { margin-top: 0.75rem; }
button, [type="submit"], [type="button"], [type="reset"], [role="button"] { --pico-font-size: 0.8125rem; --pico-font-weight: 500; --pico-form-element-spacing-vertical: 0.5rem; --pico-form-element-spacing-horizontal: 0.75rem; border-radius: 0.375rem; }
input, select, textarea { --pico-font-size: 0.875rem; }
table { --pico-table-cell-padding: 0.625rem 0.75rem; font-size: 0.875rem; }
th { font-weight: 600; }
code, kbd { border-radius: 0.25rem; }
.app-nav { border-bottom: 1px solid var(--pico-muted-border-color); }
.app-nav nav { max-width: 1200px; margin: 0 auto; padding: 0.5rem 1rem; }
.app-nav nav ul { align-items: center; }
.app-nav a { text-decoration: none; }
.app-nav a[aria-current="page"] { color: var(--pico-color); font-weight: 600; }
.section-title { display: flex; align-items: baseline; justify-content: space-between; gap: 1rem; margin: 2rem 0 0.75rem; }
.section-title h2 { margin: 0; }
.section-title small { color: var(--pico-muted-color); }
.stat { min-height: 8rem; }
.stat h2 { margin: 0.5rem 0 0.125rem; font-size: 1.75rem; letter-spacing: -0.04em; }
.stat small { color: var(--pico-muted-color); }
.muted { color: var(--pico-muted-color); }
.danger { color: #dc2626; }
[data-theme="dark"] .danger { color: #f87171; }
.positive { color: #16a34a; }
[data-theme="dark"] .positive { color: #4ade80; }
.toolbar { display: flex; align-items: end; gap: 0.5rem; flex-wrap: wrap; }
.toolbar label { margin: 0; min-width: min(100%, 15rem); }
.toolbar button { margin: 0; }
details summary { font-weight: 500; }
dialog article { max-width: 32rem; }
.theme-toggle { min-width: 5.5rem; }
</style>
</head>
<body>
<header class="app-nav">
<nav>
<ul>
<li><strong>Acme Console</strong></li>
</ul>
<ul>
<li><a href="#overview" aria-current="page">Overview</a></li>
<li><a href="#forms">Components</a></li>
<li><a href="#data">Data</a></li>
<li><button class="secondary outline theme-toggle" type="button" id="theme-toggle">Light mode</button></li>
</ul>
</nav>
</header>
<main class="container">
<header>
<h1>Compact Pro Preview</h1>
<p class="muted">Pico CSS v2 with a compact, neutral Zinc palette for actual applications and dashboards.</p>
</header>
<section id="overview">
<div class="section-title">
<h2>Dashboard</h2>
<small>Last refreshed 2 minutes ago</small>
</div>
<div class="grid">
<article class="stat">
<small class="muted">Monthly revenue</small>
<h2>€48,249</h2>
<small class="positive">+12.5% from last month</small>
</article>
<article class="stat">
<small class="muted">Active users</small>
<h2>2,350</h2>
<small class="positive">+180 this week</small>
</article>
<article class="stat">
<small class="muted">API error rate</small>
<h2>0.18%</h2>
<small class="muted">Within target threshold</small>
</article>
<article class="stat">
<small class="muted">Queued jobs</small>
<h2>14</h2>
<small class="danger">3 require attention</small>
</article>
</div>
</section>
<section id="forms">
<div class="section-title"><h2>Forms and actions</h2><small>Dense, boring, useful.</small></div>
<div class="grid">
<article>
<header><strong>Project settings</strong></header>
<form>
<label>
Project name
<input name="project" value="Production API" autocomplete="off">
</label>
<label>
Environment
<select name="environment">
<option>Development</option>
<option selected>Production</option>
<option>Staging</option>
</select>
</label>
<label>
Description
<textarea name="description" rows="3" placeholder="Optional notes for your team"></textarea>
</label>
<fieldset>
<label><input type="checkbox" checked> Enable notifications</label>
<label><input type="checkbox"> Enable maintenance mode</label>
</fieldset>
<div class="grid">
<button type="submit">Save changes</button>
<button type="button" class="secondary">Cancel</button>
</div>
</form>
</article>
<article>
<header><strong>Controls</strong></header>
<p><button type="button">Primary action</button> <button type="button" class="secondary">Secondary</button> <button type="button" class="contrast">Contrast</button></p>
<p><button type="button" class="outline">Outline</button> <button type="button" class="secondary outline">Secondary outline</button></p>
<p><button type="button" disabled>Disabled</button> <a href="#" role="button" class="outline">Link button</a></p>
<label>
Search
<input type="search" placeholder="Search users, logs, projects…">
</label>
<label>
Range: <output id="range-output">60</output>%
<input type="range" min="0" max="100" value="60" id="range-input">
</label>
<label>
Upload configuration
<input type="file">
</label>
</article>
</div>
</section>
<section id="data">
<div class="section-title"><h2>Data display</h2><small>Tables, progress, code, details.</small></div>
<article>
<header class="toolbar">
<label>
Filter events
<input type="search" placeholder="Filter by service or user">
</label>
<button type="button" class="secondary">Export CSV</button>
<button type="button">Create event</button>
</header>
<div class="overflow-auto">
<table>
<thead>
<tr><th scope="col">Event</th><th scope="col">Service</th><th scope="col">Status</th><th scope="col">Created</th><th scope="col"></th></tr>
</thead>
<tbody>
<tr><td><strong>Deployment completed</strong><br><small class="muted">build_01JH2C8</small></td><td>api-gateway</td><td><span class="positive">Healthy</span></td><td>Today, 10:42</td><td><a href="#">View</a></td></tr>
<tr><td><strong>Cache invalidated</strong><br><small class="muted">cache_01JH2B1</small></td><td>edge-cache</td><td>Completed</td><td>Today, 09:18</td><td><a href="#">View</a></td></tr>
<tr><td><strong>Worker retry threshold</strong><br><small class="muted">alert_01JH25F</small></td><td>billing-worker</td><td><span class="danger">Attention</span></td><td>Yesterday, 18:11</td><td><a href="#">View</a></td></tr>
</tbody>
</table>
</div>
<footer><small class="muted">Showing 3 of 42 events</small></footer>
</article>
<div class="grid">
<article>
<header><strong>System health</strong></header>
<label>API availability <small class="muted">99.98%</small><progress value="99.98" max="100"></progress></label>
<label>Worker capacity <small class="muted">68%</small><progress value="68" max="100"></progress></label>
<label>Storage utilisation <small class="muted">42%</small><progress value="42" max="100"></progress></label>
</article>
<article>
<header><strong>Native elements</strong></header>
<p><mark>Highlighted text</mark>, <del>deleted text</del>, <ins>inserted text</ins>, <kbd>Ctrl</kbd> + <kbd>K</kbd>.</p>
<p><code>pnpm add @picocss/pico</code></p>
<details>
<summary>Advanced settings</summary>
<p class="muted">Native disclosure works with no JavaScript. Use it for genuinely secondary controls.</p>
</details>
</article>
</div>
</section>
<section>
<div class="section-title"><h2>Typography</h2><small>Lower scale, lower drama.</small></div>
<article>
<h1>Heading level 1</h1>
<h2>Heading level 2</h2>
<h3>Heading level 3</h3>
<h4>Heading level 4</h4>
<p>Normal body text for operational applications. It is deliberately compact without becoming unpleasant to read. <a href="#">This is a normal link</a>.</p>
<blockquote>Make the default boring enough that you do not have to fight it for every internal tool.<footer>— A completely reasonable principle</footer></blockquote>
</article>
</section>
<section>
<div class="section-title"><h2>Dialog</h2><small>Requires only a small amount of native DOM API.</small></div>
<button type="button" id="open-dialog">Open dialog</button>
<dialog id="demo-dialog">
<article>
<header>
<button aria-label="Close" rel="prev" id="close-dialog"></button>
<strong>Confirm deployment</strong>
</header>
<p>This preview demonstrates Pico’s native dialog styling with the compact theme layered over it.</p>
<footer>
<button class="secondary" id="cancel-dialog" type="button">Cancel</button>
<button id="confirm-dialog" type="button">Deploy</button>
</footer>
</article>
</dialog>
</section>
</main>
<script>
const root = document.documentElement;
const toggle = document.querySelector('#theme-toggle');
const setThemeLabel = () => {
toggle.textContent = root.dataset.theme === 'dark' ? 'Light mode' : 'Dark mode';
};
toggle.addEventListener('click', () => {
root.dataset.theme = root.dataset.theme === 'dark' ? 'light' : 'dark';
setThemeLabel();
});
setThemeLabel();
const dialog = document.querySelector('#demo-dialog');
document.querySelector('#open-dialog').addEventListener('click', () => dialog.showModal());
for (const selector of ['#close-dialog', '#cancel-dialog', '#confirm-dialog']) {
document.querySelector(selector).addEventListener('click', () => dialog.close());
}
const range = document.querySelector('#range-input');
const output = document.querySelector('#range-output');
range.addEventListener('input', () => { output.value = range.value; });
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment