Vanilla HTML and CSS

Use the shared pmndrs palette, fonts and foundations with native HTML, CSS and JavaScript.

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/palette

This 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:

index.html
<!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:

src/main.ts
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:

src/style.css
: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-tokens

The 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.