Retro pixel / CRT design system for Tailwind CSS v4.
npm install halflightcssPeer dependencies (install separately if not already present):
npm install tailwindcss @tailwindcss/formsimport tailwindcss from "@tailwindcss/vite";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [tailwindcss()],
});@import "tailwindcss";
@import "halflightcss";<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=Press+Start+2P&family=DotGothic16&display=swap" rel="stylesheet" />| Token | Font | Use |
|---|---|---|
--font-pixel |
Press Start 2P | English labels, headings |
--font-pixel-ja |
DotGothic16 | Japanese-capable body, inputs |
<button class="hl-btn pixel-text text-xs">Primary</button>
<button class="hl-btn-ghost pixel-text text-xs">Ghost</button>
<button class="hl-btn-secondary pixel-text text-xs">Secondary</button>
<button class="hl-btn pixel-text text-xs" disabled>Disabled</button><label class="hl-label">Username</label>
<input class="hl-input text-sm" placeholder="Enter text..." />
<textarea class="hl-textarea text-sm" placeholder="Message..."></textarea>
<select class="hl-select text-sm">
<option>Warrior</option>
<option>Mage</option>
</select>All form elements support :focus (orange glow), ::placeholder, and :disabled.
<!-- Toggle (CSS-only via :has) -->
<label class="hl-toggle">
<input type="checkbox" checked />
</label>
<!-- Checkbox / Radio -->
<input type="checkbox" class="hl-checkbox" />
<input type="radio" class="hl-radio" />
<!-- Range -->
<input type="range" class="hl-range w-64" value="60" /><div class="hl-alert">Warning message.</div>
<div class="hl-alert-error">Error message.</div>
<div class="hl-alert-info">Info message.</div>
<div class="hl-alert-success">Success message.</div><span class="hl-badge">NEW</span>
<span class="hl-badge">LV.24</span><progress class="hl-progress" value="70" max="100"></progress>
<div class="hl-loader"></div><!-- Panel -->
<div class="hl-panel">Content</div>
<!-- Window with title bar -->
<div class="hl-window">
<div class="hl-window-title">
<span>■</span>
<span>window.exe</span>
</div>
<div class="p-4">Content</div>
</div><div class="hl-terminal crt scanline">
<p>$ halflight-css --version</p>
<p>v1.0.0</p>
<p>$ <span class="hl-terminal-cursor"></span></p>
</div><table class="hl-table text-sm">
<thead>
<tr><th>Name</th><th>LV</th><th>HP</th></tr>
</thead>
<tbody>
<tr><td>Kira</td><td>24</td><td>180</td></tr>
</tbody>
</table><a href="#" class="hl-link">Link text</a>
<code class="hl-code">hl-btn</code>
<kbd class="hl-kbd">Esc</kbd>
<kbd class="hl-kbd">Enter</kbd>
<hr class="hl-divider" /><div class="hl-statusbar">
<span class="hl-badge">APP</span>
<span>Status text</span>
<span class="ml-auto">v1.0.0</span>
</div>Fixed to the bottom of the viewport. Add pb-12 or similar to <body> to prevent content from being hidden underneath.
| Class | Description |
|---|---|
pixel-border |
4px solid black border |
pixel-shadow |
4px offset black box-shadow |
pixel-text |
Press Start 2P font |
pixelated |
image-rendering: pixelated |
crt |
Container for CRT overlay |
scanline |
Repeating scanline gradient |
orange-glow |
Box shadow glow in --hl-orange |
text-glow |
Text shadow glow in --hl-orange |
--hl-orange #ff9500 /* Primary accent */
--hl-orange-dark #2b1800 /* Panel / window background */
--hl-bg #1a0d00 /* Page background */
--hl-text #ffb347 /* Default text */
--hl-border #000000
--hl-red #ff4444 /* Error */
--hl-green #44ff88 /* Success */
--hl-blue #4499ff /* Info */hl-toggleuses:has()— requires Chrome 105+, Firefox 121+, Safari 15.4+.- Scrollbar styling (
::-webkit-scrollbar) applies in Chrome and Edge only. <select>option hover is OS-controlled and cannot be styled with CSS alone.