PSone.css: a PlayStation 1 styled CSS framework in one linked file
🎮 PS1 style CSS Framework, inspired by NES.css
At a glance
- What is it?
- A small CSS framework that skins containers, buttons, progress bars, radio buttons and inputs in the visual language of late nineties console games, shipped as a single stylesheet, with a Storybook for visual testing and a build step for the minified version.
- Who is it for?
- Adopt PSone.css if you want a distinctive retro game interface for a landing page, a kiosk or a side project and you are content to accept a small, fixed set of components rather than a configurable design system. Do not adopt it for a product that needs theming, dark mode beyond the two container variants, or accessible form primitives, since the component set is short and deliberately nostalgic rather than systematic.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly CSS, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One stylesheet, linked from a CDN
PSone.css is described as a PS1 style CSS framework, inspired by NES.css. The current state of the project is stated without ornament: at the moment there is just a CSS file that you can link to.
The link is the whole integration story:
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/98mprice/PSone.css@master/PSone.min.css">There is no build step required for a consumer, no JavaScript bundle to wire up, and no framework runtime. The whole visual identity arrives in one request.
What the framework covers is narrow and specific. A container with a title and body text, in default, dark and light variants. Buttons in five states, normal, primary, success, warning and error. Progress bars in the same five states plus an indeterminate one. A radio button styled like the PlayStation 1 memory card screen. And a text input with a label, in standalone and inline field layouts.
Each component is credited to the game it came from, which is a nice touch and also a useful way to understand the intent. The container is from Final Fantasy VII, the buttons from Tekken 3, the progress bars from Metal Gear Solid, the radio button from the PS1 memory card screen, and the input field from FF7. The homepage is a live gallery of the framework at micah5.github.io/PSone.css/.
The licence is MIT and the primary language of the repository is CSS.
Five button states and six progress bar states
The component reference is the part of the documentation that tells you what you actually get, and it is worth reading as an API.
The button set is one base class plus five modifiers:
<button type="button" class="btn">Normal</button>
<button type="button" class="btn primary">Primary</button>
<button type="button" class="btn success">Success</button>
<button type="button" class="btn warning">Warning</button>
<button type="button" class="btn error">Error</button>The progress bar follows the same naming pattern, with a wrapper carrying the state class and an inner `.bar` element whose width is set inline as a percentage, plus a `.subtitle` for the label:
<div class="progress">
<div class="bar" style="width: 80%"></div>
<div class="subtitle">Default</div>
</div>The interesting one is the indeterminate variant, which carries no inline width at all:
<div class="progress indeterminate">
<div class="bar"></div>
<div class="subtitle">indeterminate</div>
</div>That is a CSS animation of a bar whose progress is unknown, which is why the framework needs no JavaScript for it. The README does say that JavaScript is hoped for eventually, to help with progress bars among other things, which suggests the indeterminate variant is a stopgap rather than a finished feature.
The state naming is worth noting for anyone extending the framework. The vocabulary is semantic, primary, success, warning, error, rather than the numeric or intensity scales that most component libraries use, and it is consistent across buttons and progress bars, so a new component would be expected to follow the same convention.
Containers come in three variants, and the dark one is the point
The container is the component that carries the overall look, and it has three variants rather than the usual single default plus modifier:
<div class="container">
<label class="title">Default</label>
<p>Kick! Punch! It's all in the mind.</p>
</div>The dark variant is the one the framework is built around, and the copy in the reference example is the joke that makes it memorable. The light variant exists, which is a point in the framework's favour, since retro game interfaces are usually dark only.
A container is a `div` with a `label.title` and body content inside. That is a small enough surface that the markup for a whole page is basically a stack of containers, buttons and progress bars, and the visual consistency comes from the framework rather than from your own CSS.
The form components follow the same pattern. The radio button wraps a real `input` in a `label` with a `span.option` and a `span.click`, which is how the memory card selection was implemented:
<label>
<input type="radio" name="test" value="small" checked>
<span class="option">Yes
<span class="click"></span>
</span>
</label>The text input uses a `div.field` wrapper with a `label` and an `input.input`, and a `is-inline` variant for a label beside the field rather than above it.
The important detail is that the underlying HTML elements are real form controls. The radio is an actual `input type="radio"` and the text field is an actual `input type="text"`, which means keyboard and screen reader behaviour is the browser's rather than something the framework reimplements. For a novelty stylesheet that is the right call, and it is a large part of why the framework is usable at all in a page that matters.
The build produces two files and the published package lists both
The repository carries the source and the built output side by side. The top level listing includes `PSone.css` and `PSone.min.css` as well as a `src/` directory, a `scripts/` directory, `dist/`, `fonts/`, a `meta/` directory, `index.html` as the demo page, and `package.json` with a `package-lock.json`.
The build is three scripts in package.json. `build` runs `node scripts/build.mjs`, `dev` runs `node scripts/serve.mjs` and `test` runs `npm run build`, which means the test suite is the build itself. The style entry point in the package metadata is `dist/PSone.css`, and the published `files` array lists `dist`, `fonts`, `LICENSE`, `PSone.css`, `PSone.min.css` and `README.md`.
The build chain is PostCSS with `autoprefixer` and `cssnano` as the three dev dependencies, which is a conventional setup: Autoprefixer adds vendor prefixes from the browserslist targets, and cssnano minifies the output. The browserslist is `> 0.5%`, `last 2 versions` and `not dead`, and the Node engine requirement is `^22.22.0 || >=24.11.0`.
For local development, the documentation gives three commands. Forking and cloning:
git clone https://github.com/YOUR_GITHUB_USERNAME/PSone.css.git
cd PSone.css
npm installThen Storybook for visual testing, run with `npm run storybook`, and the demo server with `npm run dev`. The demo page lives in `index.html`.
Using Storybook for visual testing of a CSS framework is a good sign about how the project is maintained, since a component library is exactly the case where a visual regression harness earns its keep. The `fonts/` directory in the published files list is a reminder that the retro look depends on shipping typefaces alongside the stylesheet.
What a nostalgic framework deliberately leaves out
Three gaps follow from the design, and they are worth naming before you commit.
The first is that there is no theming system. The state classes are fixed, the variants are fixed, and the palette is what the author chose. If you need a brand colour, a dark mode that follows the operating system, or a high contrast variant, none of that is in the framework. You would be writing CSS overrides on top of it.
The second is the component count. Containers, buttons, progress bars, radio buttons and text inputs is a short list. There is no table, no modal, no navigation, no dropdown, no alert, and no layout system beyond the container. The `container` class is a boxed panel, not a grid. A real application interface built on this would be mostly your own CSS with the framework supplying a visual accent.
The third is the accessibility question, which is more nuanced than a simple yes or no. The underlying elements are semantic, which is a genuine advantage, and the retro styling is a matter of borders, colours and gradients rather than, as far as the documentation shows, of hiding focus outlines. But the documentation does not describe focus states, contrast ratios, or how the framework behaves with a screen reader, and the reference for the radio button and the input shows only the visual markup. If the interface carries meaning, that verification is yours to do.
The alternative to name is a general purpose CSS framework such as NES.css, which the project explicitly takes inspiration from, and which comes with a much larger component set. The difference in approach is that PSone.css is a focused skin for one visual era with a handful of components, while NES.css and its peers are design systems with grids, form primitives and documentation for each part.
Editorial conclusion
Adopt PSone.css if you want a distinctive retro game interface for a landing page, a kiosk or a side project and you are content to accept a small, fixed set of components rather than a configurable design system. Do not adopt it for a product that needs theming, dark mode beyond the two container variants, or accessible form primitives, since the component set is short and deliberately nostalgic rather than systematic. Verify first that the prebuilt PSone.min.css on the CDN matches the version in the repository, and check the font files, since the visual result depends on assets that have to be served alongside the stylesheet.
Frequently asked questions
How do I add PSone.css to a page?
Link the stylesheet, for example with `<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/98mprice/PSone.css@master/PSone.min.css">`. There is no JavaScript bundle to include and no build step needed for the consumer.
Which components does PSone.css provide?
Containers with a title and body in default, dark and light variants, buttons in normal, primary, success, warning and error states, progress bars in the same states plus an indeterminate variant, a radio button styled after the PS1 memory card screen, and text inputs in standalone and inline field layouts.
How do I set up PSone.css for local development?
Fork the project, then run `git clone https://github.com/YOUR_GITHUB_USERNAME/PSone.css.git`, `cd PSone.css` and `npm install`. You can then run `npm run storybook` for visual testing and `npm run dev` to serve the demo page at index.html.
How is the PSone.css package built?
The scripts are `build` which runs node scripts/build.mjs, `dev` which runs node scripts/serve.mjs, and `test` which runs the build. The chain uses postcss with autoprefixer and cssnano, and the published files list includes dist, fonts, PSone.css and PSone.min.css.
What licence is PSone.css released under?
MIT, as recorded in the package metadata and in the LICENSE file at the repository root.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/micah5-psone-css)Was this useful?