Vanilla HTML and CSS
Summary
Use the pmndrs colours and fonts with native HTML, CSS and JavaScript.
The palette item supplies light and dark CSS variables; your markup
and styles decide how to use them.
Create the app
Start with Vite's vanilla TypeScript template:
npm create vite@latest my-app -- --template vanilla-ts --no-interactive
cd my-app
npm install
npm install @fontsource-variable/inter @fontsource-variable/inconsolata
Add the palette
Install the framework-independent palette as src/assets/pmndrs.css:
pnpm dlx shadcn@latest add @pmndrs/paletteThis item copies one CSS file. It installs no components, Tailwind setup or
JavaScript runtime. The @pmndrs namespace follows main; older release tags
may not include palette.
Use the colour roles
Replace the starter index.html with a native card and a theme toggle:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Poimandres</title>
</head>
<body>
<main class="page">
<section class="card">
<h1>Hello, Poimandres</h1>
<p>Shared colours, used through <code>CSS variables</code>.</p>
<button id="scheme-toggle" type="button" aria-pressed="false">
Dark mode
</button>
</section>
</main>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
Replace src/main.ts with the imports and the toggle:
import '@fontsource-variable/inter'
import '@fontsource-variable/inconsolata'
import './assets/pmndrs.css'
import './style.css'
const toggle = document.getElementById('scheme-toggle')
if (toggle) {
toggle.addEventListener('click', () => {
const dark = document.documentElement.classList.toggle('dark')
toggle.setAttribute('aria-pressed', String(dark))
})
}
Replace src/style.css with styles using the shared roles:
:root { --radius: 0.625rem; }
body {
margin: 0;
font-family: 'Inter Variable', sans-serif;
line-height: 1.5;
background: var(--md-sys-color-background);
color: var(--md-sys-color-on-background);
}
.page {
min-height: 100dvh;
box-sizing: border-box;
padding: 2rem;
}
.card {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 1rem;
padding: 1.5rem;
border-radius: var(--radius);
background: var(--md-sys-color-surface-container-low);
color: var(--md-sys-color-on-surface);
}
h1, p { margin: 0; }
h1 { font-size: 1.5rem; font-weight: 600; }
button {
padding: 0.5rem 1rem;
border: 0;
border-radius: var(--radius);
background: var(--md-sys-color-lime-container);
color: var(--md-sys-color-on-lime-container);
font: inherit;
cursor: pointer;
}
code { font-family: 'Inconsolata Variable', monospace; }
The dark class on <html> switches the variables for the whole page.
Run npm run dev to see it.
Shared resources
Add the SVG assets and Figma tokens with the same CLI:
pnpm dlx shadcn@latest add @pmndrs/logo @pmndrs/figma-tokensThe SVGs go in public/pmndrs/; the tokens go in design/tokens/pmndrs/.
Use a logo as an ordinary image:
<img src="/pmndrs/logo_complete.svg" width="96" height="96" alt="pmndrs" />
Follow the guidelines and explore the registry catalog. Check each item's setup requirements before adding it.
Use plain HTML without Vite
Download palette.css
as pmndrs.css next to your HTML page. Copy the styles above into style.css
and link both files:
<link rel="stylesheet" href="./pmndrs.css" />
<link rel="stylesheet" href="./style.css" />
Use your project's existing fonts, or load Inter and Inconsolata through your
usual font hosting. Update the font-family declarations to match those fonts.
For the toggle, save the JavaScript below the imports from
src/main.ts as main.js, then replace the module script with
<script src="./main.js" defer></script>. The HTML, CSS and toggle use browser
APIs directly.