98.css – design system for building faithful recreations of Windows 98 UIs

2022-10-2321:41606179jdan.github.io

A design system for building faithful recreations of old UIs.

A design system for building faithful recreations of old UIs.

npm gzip size

Intro

98.css is a CSS library for building interfaces that look like Windows 98. See more on GitHub.

This library relies on the usage of semantic HTML. To make a button, you'll need to use a <button>. Input elements require labels. Icon buttons rely on aria-label. This page will guide you through that process, but accessibility is a primary goal of this project.

You can override many of the styles of your elements while maintaining the appearance provided by this library. Need more padding on your buttons? Go for it. Need to add some color to your input labels? Be our guest.

This library does not contain any JavaScript, it merely styles your HTML with some CSS. This means 98.css is compatible with your frontend framework of choice.

Here is an example of 98.css used with React, and an example with vanilla JavaScript. The fastest way to use 98.css is to import it from unpkg.

<link
  rel="stylesheet"
  href="https://unpkg.com/98.css"
>

You can install 98.css from the GitHub releases page, or from npm.

npm install 98.css

Components

A command button, also referred to as a push button, is a control that causes the application to perform some action when the user clicks it.
— Microsoft Windows User Experience p. 160

A standard button measures 75px wide and 23px tall, with a raised outer and inner border. They are given 12px of horizontal padding by default.

Show code
<button>Click me</button>
<input type="submit" />
<input type="reset" />

When buttons are clicked, the raised borders become sunken. The following button is simulated to be in the pressed (active) state.

Show code
<button>I am being pressed</button>

Disabled buttons maintain the same raised border, but have a "washed out" appearance in their label.

Show code
<button disabled>I cannot be clicked</button>

Button focus is communicated with a dotted border, set 4px within the contents of the button. The following example is simulated to be focused.

Show code
<button>I am focused</button>

A drop-down list box allows the selection of only a single item from a list. In its closed state, the control displays the current value for the control. The user opens the list to change the value.
— Microsoft Windows User Experience p. 175

Dropdowns can be rendered by using the select and option elements.

Show code
<select> <option>5 - Incredible!</option> <option>4 - Great!</option> <option>3 - Pretty good</option> <option>2 - Not so great</option> <option>1 - Unfortunate</option>
</select>

By default, the first option will be selected. You can change this by giving one of your option elements the selected attribute.

Show code
<select> <option>5 - Incredible!</option> <option>4 - Great!</option> <option selected>3 - Pretty good</option> <option>2 - Not so great</option> <option>1 - Unfortunate</option>
</select>

Window

The following components illustrate how to build complete windows using 98.css.

At the top edge of the window, inside its border, is the title bar (also reffered to as the caption or caption bar), which extends across the width of the window. The title bar identifies the contents of the window.
— Microsoft Windows User Experience p. 118
Include command buttons associated with the common commands of the primary window in the title bar. These buttons act as shortcuts to specific window commands.
— Microsoft Windows User Experience p. 122

You can build a complete title bar by making use of three classes, title-bar, title-bar-text, and title-bar-controls.

Show code
<div class="title-bar"> <div class="title-bar-text">A Title Bar</div> <div class="title-bar-controls"> <button aria-label="Close"></button> </div>
</div>

We make use of aria-label to render the Close button, to let assistive technologies know the intent of this button. You may also use "Minimize", "Maximize", "Restore" and "Help" like so:



Show code
<div class="title-bar"> <div class="title-bar-text">A Title Bar</div> <div class="title-bar-controls"> <button aria-label="Minimize"></button> <button aria-label="Maximize"></button> <button aria-label="Close"></button> </div>
</div> <br /> <div class="title-bar"> <div class="title-bar-text">A Maximized Title Bar</div> <div class="title-bar-controls"> <button aria-label="Minimize"></button> <button aria-label="Restore"></button> <button aria-label="Close"></button> </div>
</div> <br /> <div class="title-bar"> <div class="title-bar-text">A Helpful Bar</div> <div class="title-bar-controls"> <button aria-label="Help"></button> <button aria-label="Close"></button> </div>
</div>

You can make a title bar "inactive" by adding inactive class, useful when making more than one window.

Show code
<div class="title-bar inactive"> <div class="title-bar-text">An inactive title bar</div> <div class="title-bar-controls"> <button aria-label="Close"></button> </div>
</div>
Every window has a boundary that defines its shape.
— Microsoft Windows User Experience p. 118

To give our title bar a home, we make use of the window class. This provides a raised outer and inner border, as well as some padding. We can freely resize the window by specifying a width in the container style.

Show code
<div class="window" style="width: 300px"> <div class="title-bar"> <div class="title-bar-text">A Complete Window</div> <div class="title-bar-controls"> <button aria-label="Minimize"></button> <button aria-label="Maximize"></button> <button aria-label="Close"></button> </div> </div>
</div>

To draw the contents of the window, we use the window-body class under the title bar.

A Window With Stuff In It

There's so much room for activities!

Show code
<div class="window" style="width: 300px"> <div class="title-bar"> <div class="title-bar-text">A Window With Stuff In It</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"> <p>There's so much room for activities!</p> </div>
</div>
A status bar is a special area within a window, typically the bottom, that displays information about the current state of what is being viewed in the window or any other contextual information, such as keyboard state.
— Microsoft Windows User Experience p. 146

You can render a status bar with the status-bar class, and status-bar-field for every child text element.

A Window With A Status Bar

There are just so many possibilities:

  • A Task Manager
  • A Notepad
  • Or even a File Explorer!

Press F1 for help

Slide 1

CPU Usage: 14%

Show code
<div class="window" style="width: 320px"> <div class="title-bar"> <div class="title-bar-text">A Window With A Status Bar</div> </div> <div class="window-body">
<p> There are just so many possibilities:</p>
<ul> <li>A Task Manager</li> <li>A Notepad</li> <li>Or even a File Explorer!</li>
</ul> </div> <div class="status-bar"> <p class="status-bar-field">Press F1 for help</p> <p class="status-bar-field">Slide 1</p> <p class="status-bar-field">CPU Usage: 14%</p> </div>
</div>
A tree view control is a special list box control that displays a set of objects as an indented outline based on their logical hierarchical relationship.
— Microsoft Windows User Experience p. 178

To render a tree view, use an ul element with the tree-view class. The children of this list (li elements), can contain whatever you'd like.

  • We can put
  • ✨ Whatever ✨
  • We want in here
Show code
<ul class="tree-view"> <li>We can put</li> <li><strong style="color: purple">✨ Whatever ✨</strong></li> <li>We want in here</li>
</ul>

To make this a tree, we can nest further ul elements (no class needed on these). This will provide them with a nice dotted border and indentation to illustrate the structure of the tree.

To create expandable sections, wrap child lists inside of details elements.

  • Table of Contents
  • What is web development?
  • CSS
    • Selectors
    • Specificity
    • Properties
  • JavaScript
    • Avoid at all costs
    • Unless
      • Avoid
      • At
      • All
      • Cost
  • HTML
  • Special Thanks
Show code
<ul class="tree-view"> <li>Table of Contents</li> <li>What is web development?</li> <li> CSS <ul> <li>Selectors</li> <li>Specificity</li> <li>Properties</li> </ul> </li> <li> <details open> <summary>JavaScript</summary> <ul> <li>Avoid at all costs</li> <li> <details> <summary>Unless</summary> <ul> <li>Avoid</li> <li> <details> <summary>At</summary> <ul> <li>Avoid</li> <li>At</li> <li>All</li> <li>Cost</li> </ul> </details> </li> <li>All</li> <li>Cost</li> </ul> </details> </li> </ul> </details> </li> <li>HTML</li> <li>Special Thanks</li>
</ul>

Issues, Contributing, etc.

98.css is MIT licensed.

Refer to the GitHub issues page to see bugs in my CSS or report new ones. I'd really like to see your pull requests (especially those new to open-source!) and will happily provide code review. 98.css is a fun, silly project and I'd like to make it a fun place to build your open-source muscle.

Thank you for checking my little project out, I hope it brought you some joy today. Consider starring/following along on GitHub and maybe subscribing to more fun things on my twitter. 👋


Read the original article

Comments

  • By prezjordan 2022-10-2322:3411 reply

    Hey HN - author here.

    This was my burnout recovery project in April of 2020. Very much a labor of love and a surprising way to realize I still liked programming. I wrote some scattered thoughts here [0]

    I also "run" this project quite differently than I usually do - when I receive a pull request instead of merging it I do a quick glance through the user's github to make sure they're not a spammer before giving them _commit access_ and asking them to merge their own PR [1]. It has worked wonders.

    [0]: https://notes.jordanscales.com/ffa53b57

    [1]: https://twitter.com/jdan/status/1528026508564078593

    • By temporallobe 2022-10-241:272 reply

      This is awesome that it was so therapeutic to you! I have several such personal projects that I occasionally work on for similar reasons, moreover to experience the joy of pure programming as opposed to the daily BS I deal with.

      One critique (more of a suggested improvement) - the dropdown boxes don’t look/behave as they did in Win 98. They actually render as native select tags on my browser when focused and it kind of breaks the immersion. I’m pretty sure implementing this to simulate the 98 version would be a bit difficult and would involve some JavaScript (which I know you want to avoid), but it may be a neat challenge to tinker with.

    • By masswerk 2022-10-2323:261 reply

      > This was my burnout recovery project in April of 2020.

      OS UI projects are actually good for this. Back in the day, when Classic Mac OS was customizable thanks to its Theme Manager, I went through a few Kaleidoscope schemes for the same reason. Very therapeutical.

      Well done!

      • By themoonisachees 2022-10-246:26

        Strongly agree. Theming in general is a fantastic way to do what you're good at (code and design) but have more agency than "write a test and code that passes it". My goto used to be 3DS home screen themes.

    • By jks 2022-10-2410:00

      Sounds like the optimistic merging principle of the late Pieter Hintjens: http://hintjens.com/blog:106

    • By smusamashah 2022-10-240:02

      I made Obsidian's windows 98 ui theme (now almost defunct with UI overhaul) with help of this.

    • By mysterydip 2022-10-241:37

      Seeing the "hello world from VB4" brought back many fond memories. Definitely integrating this into some projects!

    • By azlyrics 2022-10-2323:21

      very fun stuff...just wanted to share this i found

      the win 98 there is using css and js. experiments thats aimed at fun is always welcome

      https://twitter.com/PCBANGio/status/1493850712471527426

    • By Gordonjcp 2022-10-2419:56

      I don't know what I'm going to do with it, but I'm going to do *something* with it.

    • By tux 2022-10-243:01

      Very nice thank you for sharing this.

    • By nashashmi 2022-10-2412:441 reply

      Were there times you felt like you were wasting your time when doing this project?

      • By prezjordan 2022-10-2414:05

        No - I tend to not take myself too seriously and was very much optimizing for smiles over "usefulness" or "github stars" so it was a self-fulfilling prophecy.

    • By dt3ft 2022-10-245:12

      Nice touch with the cowbell slider ;)

    • By RichardCNormos 2022-10-2322:47

  • By nielssp 2022-10-246:182 reply

    Tiny nitpick – buttons don't look like that when pressed in Windows 98 (or any version of Windows for that matter).

    This is what they're supposed to look like: https://imgur.com/a/iFMJCER (98.css on top, Windows 98 below)

    As far as I'm aware, the only buttons that look like that when pressed are the Start menu button and taskbar buttons.

    Similarly, buttons are supposed to have a black border in addition to the dotted outline when they're focused.

    • By prezjordan 2022-10-2415:041 reply

      Good catch - You can probably tell which parts I took from Microsoft Windows User Experience [0] and which I built while eyeing my VM.

      Unsure why there's a discrepancy. You're probably right re: taskbar buttons.

      https://i.imgur.com/dxOYj2Y.png https://i.imgur.com/X3DJ50T.png

      [0] https://www.amazon.com/Microsoft-Windows-Experience-Professi...

      • By xyzzy_plugh 2022-10-2420:54

        Probably a design bug in win98! I love that you used the book as reference. Incredible stuff.

    • By orthoxerox 2022-10-247:261 reply

      I think the thick black border marks the "default dialog button", not focus.

      • By nielssp 2022-10-247:521 reply

        It does both. Black border alone marks the default button in the dialog (unless another button is focused), black border + dotted outline marks focus.

        I double checked in a VM running Windows 98 earlier today. I suspect some of these 9x recreations are based solely on screenshots, in which details like active and focus states are not obvious.

        • By quietbritishjim 2022-10-2410:41

          To put it another way:

          * Thick black border indicates which button would be pressed if you hit enter. This is the focused button, or the default button if no button currently has focus.

          * Dashed border indicates which button or other control currently has focus; this button is pressed if you hit space (but if another control has focus then space does not press the default button).

  • By TazeTSchnitzel 2022-10-245:07

    I've previously attempted this for Windows 95. I tried very hard to be pixel-accurate. https://hikari.noyu.me/demos/ shows off a bit of what I achieved, but alas it lacks most of the UI elements.

    I learned some interesting things from the process. The biggest one for me is that web browsers have only one kind of focus, but Windows has two, a dotted line on the inside (element affected by space bar) and a black outline (element affected by return key). You therefore can't get exactly the same UI in a browser without adding some JS to simulate this second type of focus.

HackerNews