npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@vstyler96/xp.css

v2.0.0

Published

A design system for building faithful recreations of old UIs

Readme

XP.css

npm npm downloads gzip size

A design system for building faithful recreations of the Windows XP UI.

XP.css is a CSS file that takes semantic HTML and makes it look like Windows XP (Luna). It ships no JavaScript, so it works with any frontend framework.

XP.css 2.0.0 shares its markup and class names with 7.css and its sibling retro libraries (98.css, system.css, x.css). Only the look, the scope class and the variable prefix differ, so you can swap libraries without touching your HTML.

Installation

From unpkg:

<link rel="stylesheet" href="https://unpkg.com/@vstyler96/[email protected]" />

From npm:

npm install @vstyler96/xp.css
import "@vstyler96/xp.css/dist/XP.css";
<div class="window" style="width: 250px">
  <div class="title-bar">
    <div class="title-bar-text">My First Program</div>
    <div class="title-bar-controls">
      <button aria-label="Minimize"></button>
      <button aria-label="Maximize"></button>
      <button aria-label="Close"></button>
    </div>
  </div>
  <div class="window-body has-space">
    <p>Hello, world!</p>
  </div>
  <div class="window-footer">
    <button class="default">OK</button>
    <button>Cancel</button>
  </div>
</div>

Dist files

| File | What it is | | --- | --- | | dist/XP.css | Global styles. Custom properties stay live, so you can override any --xp-* variable. | | dist/XP.scoped.css | Every selector is prefixed with .winxp, so styles only apply inside <div class="winxp">. Variables live on .winxp instead of :root. | | dist/XP.inline.css | Variables resolved to plain values, for environments without custom properties. | | dist/gui/<component>.css | One file per component (button.css, window.css, …), with variables inlined. |

The pixel font loads from dist/fonts/ (and dist/gui/fonts/ for the per-component files). Keep those folders next to the CSS you serve.

Scope and variables

  • Scope class: .winxp, used only by XP.scoped.css.
  • Variable prefix: --xp-, named --xp-<component>-<property>-<state>. Components are el (element), li (list item), w (window), lv (list view) and so on. Properties are bg, bd, bdr, c, sd and grad. States are h (hover), a (active), d (disabled), hl (highlighted), f (focus) and alt.
  • Common variables: --xp-font, --xp-surface, --xp-li-bg-hl (selection blue), --xp-field-bd (text box border), --xp-lv-bg-alt and --xp-lv-bg-h.
:root {
  --xp-surface: #f1efe2;
  --xp-li-bg-hl: #2f5fb3;
}

Components

Full examples are on the documentation page.

| Component | Markup / selectors | | --- | --- | | Window | .window (.inactive, .is-bright) > .title-bar > .title-bar-text + .title-bar-controls > button[aria-label="Minimize\|Maximize\|Restore\|Help\|Close"] or .is-minimize / .is-maximize / .is-restore / .is-help / .is-close; .window-body (.has-space); .window-footer or footer; .status-bar > .status-bar-field | | Dialog | .window[role=dialog], shown when it is the :target or has [open] | | Button | button, .default, .active, .focused, :disabled, label[role=button], input[type=file] | | Checkbox | input[type=checkbox] + label[for] | | OptionButton (radio) | input[type=radio] + label[for] | | TextBox | input[type=text\|url\|email\|number\|tel\|password], textarea | | SearchBox | input[type=search], or .searchbox > input[type=search] + button[aria-label=search] | | ComboBox | .combobox > input[type=text] + button | | Dropdown | select | | ListBox | [role=listbox] > [role=option][aria-selected], or select[multiple]; .has-hover, .has-shadow | | ListView | table > thead / tbody; .has-shadow, .interactive, th.highlighted, th.indicator (.up), tr.highlighted; modifiers: .is-striped (alternate rows), .has-hover (hot-track hover row), .is-full (width: 100%), th.is-center / td.is-center | | GroupBox | fieldset > legend; .field-row, .field-row-stacked | | Tabs | menu[role=tablist] (.justified) > button[aria-selected=true][aria-controls]; sibling [role=tabpanel] | | TreeView | ul.tree-view (.has-container, .has-connector, .has-collapse-button) with nested ul and details / summary | | Collapse | details > summary | | Menu / MenuBar | ul[role=menubar] (.can-hover) > li[role=menuitem] > ul[role=menu] > li[role=menuitem]; .has-divider, [aria-haspopup], [aria-disabled] | | ProgressBar | div[role=progressbar] > div (width = value); .paused, .error, .animate, .marquee | | Slider | input[type=range], .has-box-indicator, .is-vertical wrapper | | Spinner | .spinner or .loader, .animate | | Balloon | [role=tooltip] with .is-top / .is-bottom / .is-left / .is-right | | Start button | button.start-button, pressed on :active or [aria-expanded="true"]: the green start pill | | Scrollbar | .has-scrollbar on the scrolling element (WebKit/Blink only) | | Typography | .instruction, .instruction-primary, .header-document, .header-group, a |

Development

The styles live in gui, one partial per component. They are plain PostCSS with nesting and imports, not Sass. Icons in gui/icon are inlined at build time.

Use the Makefile:

| Command | What it does | | --- | --- | | make build | Installs dependencies if package-lock.json changed, then runs npm run build to write dist/. | | make preview | Builds, then starts the watch + live-reload server on http://localhost:3000. | | make publish | npm run release: builds and publishes to npm. | | make deploy | npm run deploy:docs: builds and pushes the docs to GitHub Pages. | | make clean | Removes dist/. |

Migrating from v0.x

2.0.0 is a clean break: old names are not aliased.

  • New package name. The package moved from xp.css to @vstyler96/xp.css.
  • Only one theme. dist/98.css and dist/GUI.css are gone. Use 98.css for the Windows 98 look.
  • No global page styles. XP.css no longer styles body, headings or u. Set your own page font and background.
  • Scrollbars are opt-in. Add class="has-scrollbar" to the scrolling element (or body).
  • No global :disabled rule. Each component styles its own disabled state.
  • Progress bar markup changed. <progress value="70" max="100"> becomes:
    <div role="progressbar" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100">
      <div style="width: 70%"></div>
    </div>
    An indeterminate <progress> becomes <div role="progressbar" class="marquee"></div>.
  • Tree view decorations are opt-in. ul.tree-view adds the white box with has-container, the dotted lines with has-connector, and the +/- buttons with has-collapse-button.
  • Variables renamed. All custom properties use the --xp- prefix (for example --surface → --xp-surface, --dialog-blue → --xp-li-bg-hl, --sans-serif → --xp-font).
  • .surface and .vertical-bar removed. Use background: var(--xp-surface) instead of .surface.
  • pre uses the system monospace font. The DOS font is no longer shipped.

Issues, Contributing, etc.

New components and bug reports are welcome! See the GitHub issues page.

XP.css started as a fork of 98.css by Jordan Scales.

License

MIT