Everything starts on the pixel.
Spacing, borders, focus rings, and elevation all grow from --pp-pixel.
HTML + CSS · Optional JS · v2.1.0
A four-color interface kit for indie makers building playful websites, tools, and game screens. No framework. No runtime dependencies. Just class names that feel like cheat codes.
Pack the release, link one stylesheet, and begin the Mossmere trail with optional JavaScript only when the path needs to move.
Two files. Zero setup.
PixelPerfect is framework-neutral. Copy the release assets into your project, use semantic HTML,
and sprinkle in the pp- classes you need.
<link rel="stylesheet" href="pixelperfect.css">
<button class="pp-button">Start quest</button>
<script src="pixelperfect.iife.js"></script>
<script>PixelPerfect.init();</script>
Read Mossmere through one handheld-green palette, stepped spacing, sharp corners, and shadows you can count.
#E6F4A8#A9C46C#526B46#16231DSpacing, borders, focus rings, and elevation all grow from --pp-pixel.
The variable font ships in the release with its SIL Open Font License.
Every interactive control inherits a chunky visible keyboard focus treatment.
:root {
--pp-color-screen: #e6f4a8;
--pp-color-mid: #a9c46c;
--pp-color-shadow: #526b46;
--pp-color-ink: #16231d;
--pp-pixel: 4px;
}
Component finder
Search all 34 components by name, category, or familiar UI term.
34 components
Issue trail orders through controls that feel clicked, pressed, disabled, and busy.
Quest board · dusk watch
Awaiting a command.
Ranger's pocket tools
No tool selected.
Moonwell · 100% map scale.
<a class="pp-link" href="guide.html">Read the field guide →</a>Record every traveler with native inputs underneath and cartridge-era tactility on top.
Registry card is ready.
<div class="pp-field">
<label class="pp-label" for="hero">Hero name</label>
<input id="hero" class="pp-input" type="text" aria-describedby="hero-help">
<p id="hero-help" class="pp-help">2–20 characters.</p>
</div>Rune rejected. Try MOSS-21.
<input class="pp-input" type="text" aria-invalid="true" aria-describedby="save-error">
<p id="save-error" class="pp-error">That rune is not in this realm.</p>0 runes recorded.
<label class="pp-label" for="notes">Quest notes</label>
<textarea id="notes" class="pp-textarea" placeholder="The old bridge…"></textarea>Heroic hike selected.
<select class="pp-select" aria-label="Difficulty">
<option>Story stroll</option>
<option selected>Heroic hike</option>
</select>1 registry option enabled.
<label class="pp-check">
<input type="checkbox" checked> Show map markers
</label>Moth familiar is waiting.
<label class="pp-radio">
<input type="radio" name="familiar" checked> Moth
</label>Camp music on · shake off.
<label class="pp-switch">
<input type="checkbox" role="switch" checked>
<span class="pp-switch__track" aria-hidden="true"></span>
<span>Music</span>
</label>Lantern hum set to 72%.
<label class="pp-label" for="volume">Sound volume</label>
<input id="volume" class="pp-range" type="range" min="0" max="100" value="72">PNG only. Keep it tiny.
No sprite parcel attached.
<label class="pp-label" for="sprite">Upload character sprite</label>
<input id="sprite" class="pp-file-input" type="file" accept="image/png">Carry loot, lore, records, party members, and every useful moonspore found between them.
Glows faintly around soup.
No item equipped.
<article class="pp-card pp-stack">
<span class="pp-badge">Rare</span>
<h3>Moonspore blade</h3>
<p>Glows faintly around soup.</p>
</article>Follow the glow past the old mill.
Quest is unpinned.
<section class="pp-panel">
<header class="pp-panel__titlebar">Quest log</header>
<div class="pp-panel__body">Follow the glow…</div>
</section>Deep cave save selected.
<ul class="pp-list" aria-label="Save files">
<li>Meadow · 02:14</li>
<li aria-selected="true">Deep cave · 06:42</li>
</ul>| Hero | HP | LV |
|---|---|---|
| Moss | 8/8 | 12 |
| Moth | 3/3 | 9 |
<div class="pp-table-wrap">
<table class="pp-table">
<thead><tr><th scope="col">Hero</th><th scope="col">HP</th></tr></thead>
<tbody><tr><td>Moss</td><td>8/8</td></tr></tbody>
</table>
</div><span class="pp-avatar" aria-label="Moss Knight">MK</span>
<span class="pp-avatar pp-avatar--small" aria-label="Moth">MO</span><span class="pp-badge">NEW</span>Showing cozy quests.
<span class="pp-tag">cozy</span>
<span class="pp-tag">tiny dragons</span>Make every save, warning, wait, and recovery visible without breaking the spell.
Checkpoint glow ready.
<div class="pp-alert" role="status">
<div><strong>Checkpoint reached.</strong> Your progress is safe.</div>
<button data-pp-dismiss aria-label="Dismiss alert">×</button>
</div>Moonwell route is 62% complete.
<progress class="pp-progress" value="62" max="100">62%</progress><meter class="pp-meter" min="0" max="10" low="3" high="7" optimum="10" value="4">4 of 10</meter>Arrival signal ready.
<div role="status">
<span class="pp-spinner" aria-hidden="true"></span>
<span>Entering dungeon…</span>
</div><div aria-busy="true" aria-label="Loading item details">
<span class="pp-skeleton"></span>
<span class="pp-skeleton"></span>
</div><span class="pp-tooltip" data-pp-tooltip="Restores 3 hearts">
<button class="pp-icon-button" aria-label="Health potion details">…</button>
</span>PixelPerfect.toast().No shrine messages replayed.
const notice = PixelPerfect.toast('Quest saved to slot B.', {
tone: 'success',
duration: 4000
});
// Optional early cleanup
notice.dismiss();Rest, reorganize, and return through native dialogs and focus-friendly drawers.
Moonlit campfire
No rest taken.
<button class="pp-button" data-pp-dialog-open="#rest-dialog">Rest at camp</button>
<dialog id="rest-dialog" class="pp-dialog">
<div class="pp-dialog__body">…</div>
<button data-pp-dismiss>Keep walking</button>
</dialog>Pack beside the tent
Pack closed · Moonspore blade equipped.
<button data-pp-drawer-open="#inventory">Open inventory</button>
<aside id="inventory" class="pp-drawer" aria-hidden="true" aria-label="Inventory">
<button data-pp-dismiss>Close</button>
</aside>Every small primitive now travels together through one complete Mossmere interface.