@vstyler96/xp.css
v2.0.0
Published
A design system for building faithful recreations of old UIs
Readme
XP.css
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.cssimport "@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 byXP.scoped.css. - Variable prefix:
--xp-, named--xp-<component>-<property>-<state>. Components areel(element),li(list item),w(window),lv(list view) and so on. Properties arebg,bd,bdr,c,sdandgrad. States areh(hover),a(active),d(disabled),hl(highlighted),f(focus) andalt. - Common variables:
--xp-font,--xp-surface,--xp-li-bg-hl(selection blue),--xp-field-bd(text box border),--xp-lv-bg-altand--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.cssto@vstyler96/xp.css. - Only one theme.
dist/98.cssanddist/GUI.cssare gone. Use 98.css for the Windows 98 look. - No global page styles. XP.css no longer styles
body, headings oru. Set your own page font and background. - Scrollbars are opt-in. Add
class="has-scrollbar"to the scrolling element (orbody). - No global
:disabledrule. Each component styles its own disabled state. - Progress bar markup changed.
<progress value="70" max="100">becomes:
An indeterminate<div role="progressbar" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100"> <div style="width: 70%"></div> </div><progress>becomes<div role="progressbar" class="marquee"></div>. - Tree view decorations are opt-in.
ul.tree-viewadds the white box withhas-container, the dotted lines withhas-connector, and the +/- buttons withhas-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). .surfaceand.vertical-barremoved. Usebackground: var(--xp-surface)instead of.surface.preuses 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.
