99.css


A design system for building faithful recreations of old UIs.

Intro

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

My First VB4 Program

Hello, world!

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 99.css is compatible with your frontend framework of choice.

Install it from npm and import it in your entry file:

npm install 99.css
import "99.css";

Or link it straight from a CDN, no build step required:

<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/99.css"
>

Modules

Every component lives in its own file. Import the core (tokens.css, fonts.css, base.css) and only the components you need:

import "99.css/tokens.css";
import "99.css/fonts.css";
import "99.css/base.css";
import "99.css/button.css";
import "99.css/window.css";

Scaling

Every size is a multiple of --px, which is 1px * var(--scale). Bevel lines are rounded down to whole pixels, so borders stay crisp at fractional scales. Integer scales look best with the pixel font.

:root {
  --scale: 1.5;
}

To scale a part of the page only, mark it with data-scale:

<div data-scale style="--scale: 2">...</div>

Components

Button

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.

You can add the class default to any button to apply additional styling, useful when communicating to the user what default action would happen in the active window if the Enter key was pressed on Windows 98.

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

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

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

Checkbox

A check box represents an independent or non-exclusive choice.
— Microsoft Windows User Experience p. 167

Checkboxes are represented with a sunken panel, populated with a "check" icon when selected, next to a label indicating the choice.

Note: You must include a corresponding label after your checkbox, using the <label> element with a for attribute pointed at the id of your input. This ensures the checkbox is easy to use with assistive technologies, on top of ensuring a good user experience for all (navigating with the tab key, being able to click the entire label to select the box).

Checkboxes can be selected and disabled with the standard checked and disabled attributes.

When grouping inputs, wrap each input in a container with the field-row class. This ensures a consistent spacing between inputs.

OptionButton

An option button, also referred to as a radio button, represents a single choice within a limited set of mutually exclusive choices. That is, the user can choose only one set of options.
— Microsoft Windows User Experience p. 164

Option buttons can be used via the radio type on an input element.

Option buttons can be grouped by specifying a shared name attribute on each input. Just as before: when grouping inputs, wrap each input in a container with the field-row class to ensure a consistent spacing between inputs.

Option buttons can also be checked and disabled with their corresponding HTML attributes.

GroupBox

A group box is a special control you can use to organize a set of controls. A group box is a rectangular frame with an optional label that surrounds a set of controls.
— Microsoft Windows User Experience p. 189

A group box can be used by wrapping your elements with the fieldset tag. It contains a sunken outer border and a raised inner border, resembling an engraved box around your controls.

Select one:

You can provide your group with a label by placing a legend element within the fieldset.

Today's mood

TextBox

A text box (also referred to as an edit control) is a rectangular control where the user enters or edits text. It can be defined to support a single line or multiple lines of text.
— Microsoft Windows User Experience p. 181

Text boxes can rendered by specifying a text type on an input element. As with checkboxes and radio buttons, you should provide a corresponding label with a properly set for attribute, and wrap both in a container with the field-row class.

Additionally, you can make use of the field-row-stacked class to position your label above the input instead of beside it.

To support multiple lines in the user's input, use the textarea element instead.

Text boxes can also be disabled and have value with their corresponding HTML attributes.

Slider

A slider, sometimes called a trackbar control, consists of a bar that defines the extent or range of the adjustment and an indicator that shows the current value for the control...
— Microsoft Windows User Experience p. 146

Sliders can rendered by specifying a range type on an input element.

You can make use of the has-box-indicator class replace the default indicator with a box indicator, furthermore the slider can be wrapped with a div using is-vertical to display the input vertically.

Note: To change the length of a vertical slider, the input width and div height.

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.

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

Window

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

Title Bar

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.

A Title Bar

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:

A Title Bar

A Maximized Title Bar

A Helpful Bar

Each aria-label also has a corresponding styling class to render the title bar buttons, to let the aria-label text be in other languages without causing rendering, accessibility, or localization issues.

A Title Bar using Button Styling Classes

A Maximized Title Bar using Button Styling Classes

A Helpful Bar using Button Styling Classes

Maximize buttons can be disabled, useful when making a window appear as if it cannot be maximized.

A Title Bar with Maximize disabled

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

An inactive title bar

Window contents

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.

A Complete Window

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!

Status Bar

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%

TreeView

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

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
        • Avoid
        • At
        • All
        • Cost
      • All
      • Cost
  • HTML
  • Special Thanks

Tabs

A tab control is analogous to a divider in a file cabinet or notebook. You can use this control to define multiple logical pages or sections of information within the same window.
— Microsoft Windows User Experience p. 193

To render a tab list, use a menu element with the [role=tablist] attribute. The children of this menu (li elements), should get a [role=tab] attribute.

Tabs should be managed by adding custom javascript code. All you need is to add the [aria-selected=true] attribute to the active tab.

To create multirows tabs, add a multirows class to the menu tag.

TableView

To render a table view, use a table element. Wrap it with a div element with sunken-panel class to provide proper border and overflow container.

With a bit of extra scripting you can make table view interactive. Give interactive class to table element to show pointer cursor when hovering over body rows. Table rows can be given highlighted class to appear selected.

Name Version Company
MySQL ODBC 3.51 Driver 3.51.11.00 MySQL AB
SQL Server 3.70.06.23 Microsoft Corporation
SQL Server 3.70.06.23 Microsoft Corporation
SQL Server 3.70.06.23 Microsoft Corporation
SQL Server 3.70.06.23 Microsoft Corporation
SQL Server 3.70.06.23 Microsoft Corporation
SQL Server 3.70.06.23 Microsoft Corporation
SQL Server 3.70.06.23 Microsoft Corporation
SQL Server 3.70.06.23 Microsoft Corporation
SQL Server 3.70.06.23 Microsoft Corporation

Progress Indicator

You can use a progress indicator, also known as a progress bar control, to show the percentage of completion of a lengthy operation.
— Microsoft Windows User Experience p. 189

There are two types of progress bars: solid and segmented. The solid version is the default. To declare a segmented bar, you should use the segmented class.

Field borders

Text boxes, check boxes, drop-down list boxes, spin boxes and list boxes use the field border style. You can also use the style for define the work area within a window. It uses the sunken outer and sunken inner basic border styles. For most controls, the interior of the field uses the button highlight color. For text fields, such as text boxes and combo boxes, the interior uses the button face color when the field is read-only or disabled.
— Microsoft Windows User Experience p. 421
Status fields use the status field border style. This style uses only the sunken outer basic border style. You use the status field style in status bars and other read-only fields where the content of the file can change dynamically.
— Microsoft Windows User Experience p. 422

As mentioned in these guidelines, these styles are used in other contexts than just form elements and status fields such as to indicate work areas and dynamic content. For that reason, we provide three classes for these generic usages, field-border, field-border-disabled, and status-field-border. These classes only define the border and background color and minimal padding, so you will typically need to at least provide some extra padding yourself.

Work area
Disabled work area
Dynamic content

Issues, Contributing, etc.

99.css is MIT licensed.

Refer to the GitHub issues page to see bugs or report new ones. Pull requests are very welcome.

Thank you for checking this project out. 👋