- 98.cssは、セマンティックHTMLとアクセシビリティを基盤に、Windows 98風に見えるWebインターフェースを実装するCSSデザインシステム
- JavaScriptなしでHTMLにスタイルだけを適用するため、ReactやバニラJavaScriptをはじめとするさまざまなフロントエンド環境で利用できる
- ボタン、入力欄、選択コントロールから、ウィンドウ、タブ、ツリー、表、進捗バーまで、幅広いWindows 98 UIコンポーネントを提供
- ラベルの関連付け、
aria-label、ARIAロールをサポートし、基本の外観を保ちながら余白や色などのスタイルも上書きできる
- unpkg、npm、GitHub Releasesでインストールでき、MITライセンスで配布されているため、改変やオープンソースへの貢献が可能
プロジェクト構成とインストール
- 98.cssは、Windows 98インターフェースを忠実に再現するCSSライブラリ
- セマンティックHTMLをベースに、ボタンには
<button>、入力要素には <label>、アイコンボタンには aria-label を使う
- 主な目標にアクセシビリティが含まれており、キーボードナビゲーションと支援技術の利用を考慮している
- JavaScriptなしでCSSだけでHTMLを装飾するため、特定のフロントエンドフレームワークに依存しない
- 最も手早い使い方は、unpkgからスタイルシートを読み込むこと
<link rel="stylesheet" href="https://unpkg.com/98.css">
npm install 98.css
- 基本の外観を保ちながら、ボタンの余白や入力ラベルの色など、個別のスタイルを自由に上書きできる
基本的な選択コントロール
-
ボタン
- 標準ボタンは 75×23px サイズで、盛り上がった外側・内側の境界線と、デフォルトで12pxの左右余白を持つ
<button>、input[type=submit]、input[type=reset]をサポートする
default クラスは、アクティブなウィンドウでEnterキーを押したときに実行されるデフォルト動作を表す
- クリックすると、盛り上がった境界線が押し込まれた形に変わり、無効なボタンは境界線を保ったままラベルが薄く表示される
- フォーカスは、ボタン内容の内側4px位置にある点線の境界線で表示される
-
チェックボックスとラジオボタン
- チェックボックスは独立した選択、または排他的でない選択を表し、選択されると押し込まれたパネル内にチェックアイコンが表示される
- チェックボックスの後ろには、入力の
id を指す for 属性を持つ <label> が必ず必要
- この関連付けにより、支援技術が入力を認識できる
- Tabキーによるナビゲーションと、ラベル全体のクリックをサポートする
- 標準の
checked、disabled 属性で選択状態と無効状態を指定する
- 複数の入力は
field-row コンテナで囲み、一貫した間隔を適用する
- ラジオボタンは、限られた集合から1つだけを選ぶコントロールで、
input[type=radio] で作成する
- 同じ
name 属性を指定して相互排他的なグループにまとめ、チェックボックスと同様にラベルと field-row を使う
-
グループボックス
fieldset は複数のコントロールを長方形のフレームでまとめ、押し込まれた外側の境界線と盛り上がった内側の境界線により、彫り込まれた箱のような見た目を作る
- 内部に
legend を配置すると、グループラベルを表示できる
テキスト入力と値の選択
-
テキストボックス
- 1行入力は
input[type=text]、複数行入力は textarea で構成する
- 入力と正しく関連付けられたラベルを
field-row で一緒に囲み、横並びに配置する
field-row-stacked を使うと、ラベルを入力要素の上に縦方向に配置できる
- 標準HTMLの
disabled、value 属性で無効状態と初期値を指定する
-
スライダー
- スライダーは調整範囲と現在値を表し、
input[type=range] でレンダリングする
has-box-indicator クラスは、デフォルトのインジケーターを箱型インジケーターに置き換える
- スライダーを
is-vertical クラスが適用された div で囲むと、縦方向に表示できる
- 縦スライダーの長さは、
input の幅とコンテナ div の高さで調整する
-
ドロップダウン
select と option で、リストから1つの項目を選択するドロップダウンを作る
- 最初の項目がデフォルトで選択され、別の
option に selected 属性を指定して初期選択を変更できる
Windows 98スタイルのウィンドウ
-
タイトルバー
- タイトルバーはウィンドウ上部の全幅に配置され、内容を識別し、一般的なウィンドウコマンドボタンを含む
title-bar、title-bar-text、title-bar-controls の3つのクラスで構成する
- コマンドボタンの
aria-label には Minimize、Maximize、Restore、Help、Close を使える
aria-label はボタンの意図を支援技術に伝えると同時に、コマンドに合ったアイコンスタイルも適用する
- 別途
minimize、maximize、restore、help、close クラスも提供する
aria-label のテキストと視覚スタイルを分離し、多言語・ローカライズの過程でレンダリングやアクセシビリティの問題が起きないようにしている
- 最大化できないウィンドウでは、Maximizeボタンに
disabled を指定する
title-bar inactive で、複数のウィンドウのうち非アクティブなタイトルバーを表現する
-
ウィンドウ本文とステータスバー
window クラスは、盛り上がった外側・内側の境界線と余白を提供し、コンテナ幅を指定してウィンドウサイズを変えられる
- タイトルバー下の実際のコンテンツは
window-body に配置する
- ウィンドウ下部のステータスバーは、現在の状態やキーボード状態などのコンテキスト情報を示す
- 全体のコンテナには
status-bar、各テキスト領域には status-bar-field を使う
- ステータスバーを活用して、Task Manager、Notepad、File Explorerのようなインターフェースを構成できる
階層・タブ・表インターフェース
-
ツリービュー
ul.tree-view は、オブジェクト間の論理的な階層をインデントされたリストで表現する
- 下位の
ul をネストすると点線の境界線とインデントが適用され、内部の li には任意のコンテンツを入れられる
- 展開・折りたたみ可能な階層は、子リストを
details 要素の中に配置して構成する
-
タブ
- タブリストは
menu[role=tablist]、各タブは li[role=tab] で記述する
- アクティブなタブには
aria-selected="true" を指定する
- 98.cssにはタブ切り替えロジックがないため、状態変更はユーザー側のJavaScriptで管理する必要がある
- タブコンテンツは
role="tabpanel" が指定されたウィンドウ領域に配置する
menu に multirows クラスを追加すると、複数行のタブを作成できる
-
表ビュー
- HTMLの
table を div.sunken-panel で囲み、適切な境界線とスクロール可能な領域を作る
table.interactive は、本体行にマウスを重ねたときにポインターカーソルを表示する
- 選択された行には
highlighted クラスを適用し、実際の行選択動作は別途スクリプトで実装する
進捗状態と汎用境界線
-
進捗バー
- 長い作業の完了率は、
progress-indicator の中に progress-indicator-bar を配置し、幅で指定する
- 基本形は単色バーで、
segmented クラスを追加すると分割型の進捗バーに変わる
-
フィールド境界線
- テキストボックス、チェックボックス、ドロップダウン、スピンボックス、リストボックスは、押し込まれた外側・内側の境界線のフィールドスタイルを使う
- 通常フィールドは内部にボタン強調色を使い、読み取り専用または無効なテキストフィールドはボタン表面色を使う
- ステータスフィールドには押し込まれた外側の境界線だけを適用し、ステータスバーや動的に変わる読み取り専用コンテンツで活用する
- フォーム以外の作業領域や動的コンテンツにも使えるよう、3つの汎用クラスを提供する
field-border: 通常の作業領域
field-border-disabled: 無効な作業領域
status-field-border: 動的ステータスコンテンツ
- これらのクラスは境界線、背景色、最小限の余白だけを定義するため、通常は追加の
padding を自分で指定する必要がある
ライセンスと貢献
- 98.cssは MITライセンスで配布されている
- バグの確認と報告は GitHub Issuesで行える
- プルリクエストを受け付け、コードレビューを提供しており、特にオープンソースに初めて貢献する参加者を歓迎している
1件のコメント
Hacker News の意見
このプロジェクトはバーンアウトからの回復過程で作ったもので、今でも特別に大切にしている
https://notes.jordanscales.com/98-css-reflections
使いやすさと懐かしさのバランスが絶妙で、他のプロジェクトでももっと活用したくなった
調べているうちに98.css作者のポートフォリオも見つけたが、音楽の好みまで完全に同じで、レトロ風ライブラリを作る人たちは皆似た趣味なのか気になった
フラットデザインはばかげているのに、誰かに大金を稼がせたあと、皆が羊の群れのように追随している
ほぼ20年たっても抜け出せていないのも、もはや驚きではないし、昔のUIで複数行タブが自然に機能していたやり方は本当に見事だった
「少ないほどよい」という哲学が、Apple・Googleとその模倣者たちの過飽和な玩具粘土のようなUIと衝突しているだけだ
貴重な縦方向のスペースを占有し、クリックするたびに行の位置が変わって混乱したし、状態を示すボタンならクリック後に動いてはいけない
何百万色も表示できるモニターとグラフィックカードを持っていても活用していない。塗り絵のようにする必要はないが、Windows 10と11は陰気に感じる
98.css系でいつも気になっていたのは、MS Sans Serifが微妙に不正確だという点で、結局自分で修正することにした
https://github.com/jdan/98.css/pull/230
このプロジェクトは以前にも何度も人気を集めている: 2024年 471ポイント・コメント93件 https://news.ycombinator.com/item?id=42056918、2022年 606ポイント・コメント182件 https://news.ycombinator.com/item?id=33310554、2020年 838ポイント・コメント211件 https://news.ycombinator.com/item?id=22940564
Windows 95: https://alexbsoft.github.io/win95.css/, 1980年代のWebサイト: https://bootstra386.com/, Windows XP: https://botoxparty.github.io/XP.css/, GeoCities: https://code.divshot.com/geo-bootstrap/, Counter-Strike 1.6: https://cs16.samke.me/, Edward Tufte: https://edwardtufte.github.io/tufte-css/, Windows 98: https://jdan.github.io/98.css/, Windows 7: https://khang-nd.github.io/7.css/, PlayStation: https://micah5.github.io/PSone.css/, NES: https://nostalgic-css.github.io/NES.css/, Apple System: https://sakofchit.github.io/system.css/, SNES: https://snes-css.sadlative.com/, The Sims: https://thesimscss.inbn.dev/
このスタイルを適用するWebサイトを作りたいが、どこに合うのか思いつかない
LinuxをWindows XP風に見せる XFCE-winxp-tc も素晴らしい。Chicago95はよく知られているが、2004年ごろの雰囲気が欲しいなら https://github.com/rozniak/xfce-winxp-tc がよく合う
法的な懸念のためなのかは分からない
無効化されたボタンをなくして、そもそも表示しないやり方は、今日もっとも混乱を招く UIトレンド の一つであり、グレーのボタンを見るとむしろ安心する
ユーザーが適用可能だと予想し、無効化されている理由を容易に推測できる場合にだけ無効にし、有効化する方法がない、または適用されるとは予想しない場合は削除すべきだとしていた。理由が分かりにくいなら、有効な状態のままにして、誤って使ったときに有用なエラーメッセージを表示するほうがよい
https://learn.microsoft.com/en-us/windows/win32/uxguide/top-...
しかし現代のガイドライン https://learn.microsoft.com/en-us/windows/apps/develop/ui/co... では、こうした微妙な区別はもちろん、無効化ボタン自体も扱っていない
一方で、実行権限はあるが現在のモードや状態のためにできない場合は、グレーのボタン を見せるべきだ。フォームではグレーのボタンもクリックできるようにし、何が間違っているのかを知らせる必要がある。ある大手航空会社では、こうした案内がなかったためチェックインを完了できなかった
マウスオーバーのヘルプや小さな
?表示は消え、すべてのソフトウェアが初日から使い方を知っていることを前提にしているようだhttps://ka.ge は98.cssで作られた個人サイトで、1MB未満 でWindows 98のデスクトップ環境をピクセル単位で正確かつ実際に動作する形で再現している
複数行タブの例で、クリックしたときにタブが本来のWindowsのように ランダムに位置を変えないこと は惜しい
OSの新バージョンのたびに、UIデザイナーは機能的には不要で、リソースをより多く使い、遅く不安定な変更であっても 改善だと包装 しなければならなかった
less fasterという表現を見ると、そのUIデザイナーたちがこのコメントにも手を入れたようだWindows 98のUIがユーザー体験の頂点というわけでもないのに、こうした再現作業に注力する理由は理解しにくい
今日の肥大化は、技術と 抽象化レイヤー が何層にも積み重なった結果なので、良いユーザー体験に必要な要素を理解し、最小限の技術構成要素を見つけることが核心だ
角丸や浮いた余白が代表例であり、macOSとWebデザイナーの影響はユーザビリティを損ねた