A monochrome, dark-only CSS library. Glassmorphism meets terminal-editorial aesthetic. Zero dependencies, zero build step.
- Add the Inter font to your
<head>:
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&display=swap" rel="stylesheet">- Link endark:
<link rel="stylesheet" href="path/to/endark.css" />That's it. No build tools, no preprocessors, no JavaScript.
Import only what you need instead of the full bundle:
<link rel="stylesheet" href="path/to/endark/src/tokens.css" />
<link rel="stylesheet" href="path/to/endark/src/base.css" />
<!-- add more layers as needed -->| Layer | File | What it provides |
|---|---|---|
| Tokens | src/tokens.css |
CSS custom properties (colors, spacing, type, timing) |
| Base | src/base.css |
Reset, body defaults, scrollbar, selection |
| Typography | src/typography.css |
Headings, text utilities, prose styling |
| Glass | src/glass.css |
Glass surfaces, cards, inputs, buttons, badges |
| Layout | src/layout.css |
Container, topbar, page header, footer, sections |
| Content | src/content.css |
List items, stat cards, skeletons, spinners, badges |
| Animations | src/animations.css |
Keyframes, animation utilities, stagger support |
All CSS custom properties are prefixed with --ed- to avoid collisions.
Strictly monochrome — grays are the only colors allowed.
| Token | Value |
|---|---|
--ed-black |
#000000 |
--ed-gray-950 |
#0a0a0a |
--ed-gray-900 |
#171717 |
--ed-gray-800 |
#262626 |
--ed-gray-700 |
#404040 |
--ed-gray-600 |
#525252 |
--ed-gray-500 |
#737373 |
--ed-gray-400 |
#a3a3a3 |
--ed-gray-300 |
#d4d4d4 |
--ed-gray-200 |
#e5e5e5 |
--ed-gray-100 |
#f5f5f5 |
--ed-gray-50 |
#fafafa |
--ed-white |
#ffffff |
| Token | Maps to |
|---|---|
--ed-color-bg |
--ed-black |
--ed-color-surface |
--ed-gray-950 |
--ed-color-surface-hover |
--ed-gray-900 |
--ed-color-text |
--ed-gray-300 |
--ed-color-text-muted |
--ed-gray-500 |
--ed-color-text-faint |
--ed-gray-700 |
--ed-color-heading |
--ed-white |
--ed-color-border |
--ed-gray-800 |
--ed-color-border-hover |
--ed-gray-600 |
| Token | Value |
|---|---|
--ed-space-xs |
0.25rem (4px) |
--ed-space-sm |
0.5rem (8px) |
--ed-space-md |
1rem (16px) |
--ed-space-lg |
1.5rem (24px) |
--ed-space-xl |
2rem (32px) |
--ed-space-2xl |
3rem (48px) |
--ed-space-3xl |
4rem (64px) |
--ed-space-4xl |
6rem (96px) |
| Token | Value |
|---|---|
--ed-radius-sm |
4px |
--ed-radius-md |
8px |
--ed-radius-lg |
12px |
| Token | Value |
|---|---|
--ed-ease-out |
cubic-bezier(0.16, 1, 0.3, 1) |
--ed-duration-fast |
150ms |
--ed-duration-base |
300ms |
--ed-duration-slow |
500ms |
<div class="ed-glass-card">
<h3>Title</h3>
<p>Content goes here.</p>
</div><input type="text" class="ed-glass-input" placeholder="Type here..." />
<textarea class="ed-glass-input" placeholder="Write..."></textarea>
<select class="ed-glass-input">
<option>Pick one</option>
</select><button class="ed-glass-btn">Ghost</button>
<button class="ed-btn-primary">Primary</button><header class="ed-topbar">
<a href="/" class="ed-topbar-logo">Brand</a>
<nav class="ed-topbar-nav">
<a href="/about" class="ed-topbar-link">About</a>
<a href="/work" class="ed-topbar-link active">Work</a>
<a href="/blog" class="ed-topbar-link">Blog</a>
</nav>
</header><div class="ed-page-header">
<h1 class="ed-title">Page Title</h1>
<p class="ed-subtitle">A brief description.</p>
</div><a href="/post/1" class="ed-list-item">
<div class="ed-list-item-title">Post Title</div>
<div class="ed-list-item-description">A short summary.</div>
<div class="ed-list-item-meta">
<span>Feb 2026</span>
<span>5 min</span>
</div>
</a><div class="ed-stat-grid">
<div class="ed-stat-card">
<div class="ed-stat-value">142</div>
<div class="ed-stat-label">Solved</div>
</div>
<div class="ed-stat-card">
<div class="ed-stat-value">99%</div>
<div class="ed-stat-label">Uptime</div>
</div>
</div><span class="ed-badge">default</span>
<span class="ed-badge ed-badge--success">accepted</span>
<span class="ed-badge ed-badge--error">rejected</span>
<span class="ed-glass-badge">glass badge</span><div class="ed-skeleton-card">
<div class="ed-skeleton ed-skeleton--w-50" style="height: 1rem; margin-bottom: 1rem;"></div>
<div class="ed-skeleton-text ed-skeleton--w-full"></div>
<div class="ed-skeleton-text ed-skeleton--w-75"></div>
<div class="ed-skeleton-text ed-skeleton--w-50"></div>
</div><div class="ed-spinner ed-spinner--sm"></div>
<div class="ed-spinner"></div>
<div class="ed-spinner ed-spinner--lg"></div><div class="ed-prose">
<h2>Article Title</h2>
<p>Body text with <strong>bold</strong>, <em>italic</em>, and <a href="#">links</a>.</p>
<blockquote>A quote.</blockquote>
<pre><code>const x = 42;</code></pre>
</div><!-- Fade in -->
<div class="ed-animate-fade-in">...</div>
<!-- Fade up (most common entry animation) -->
<div class="ed-animate-fade-up">...</div>
<!-- Staggered entry -->
<div class="ed-animate-fade-up ed-stagger" style="--ed-delay: 0ms">First</div>
<div class="ed-animate-fade-up ed-stagger" style="--ed-delay: 50ms">Second</div>
<div class="ed-animate-fade-up ed-stagger" style="--ed-delay: 100ms">Third</div>
<!-- Transition helpers -->
<div class="ed-transition">Smooth hover</div>
<div class="ed-transition-fast">Quick hover</div>All animations respect prefers-reduced-motion: reduce.
Override any --ed-* variable on :root to customize the theme:
:root {
--ed-color-bg: #0a0a0a;
--ed-radius-lg: 16px;
--ed-font-sans: "IBM Plex Sans", sans-serif;
}Modern browsers with CSS custom properties and backdrop-filter support:
- Chrome 76+
- Firefox 103+
- Safari 14+
- Edge 79+
MIT