1 Punkte von GN⁺ 3 시간 전 | 1 Kommentare | Auf WhatsApp teilen
  • 98.css ist ein CSS-Designsystem, das auf semantischem HTML und Barrierefreiheit basiert und Web-Oberflächen im Stil von Windows 98 umsetzt
  • Da nur Styles auf HTML angewendet werden und kein JavaScript nötig ist, kann es in verschiedenen Frontend-Umgebungen verwendet werden, darunter React und Vanilla JavaScript
  • Es bietet eine breite Palette an Windows-98-UI-Komponenten, von Buttons, Eingabefeldern und Auswahl-Controls bis hin zu Fenstern, Tabs, Bäumen, Tabellen und Fortschrittsbalken
  • Es unterstützt Label-Verknüpfungen, aria-label und ARIA-Rollen; außerdem lassen sich einzelne Styles wie Abstände oder Farben neu definieren, ohne die Grundoptik zu verlieren
  • Installation ist über unpkg, npm und GitHub Releases möglich, und die Veröffentlichung unter der MIT-Lizenz erlaubt Anpassungen und Open-Source-Beiträge

Projektaufbau und Installation

  • 98.css ist eine CSS-Bibliothek, die die Windows-98-Oberfläche originalgetreu nachbildet
  • Sie basiert auf semantischem HTML und verwendet für Buttons <button>, für Eingabeelemente <label> und für Icon-Buttons aria-label
  • Zu den wichtigsten Zielen gehört Barrierefreiheit, einschließlich Keyboard-Navigation und Unterstützung für assistive Technologien
  • Da HTML nur mit CSS gestaltet wird und kein JavaScript nötig ist, besteht keine Abhängigkeit von einem bestimmten Frontend-Framework
  • Die schnellste Nutzungsmethode ist das Einbinden des Stylesheets über unpkg
<link rel="stylesheet" href="https://unpkg.com/98.css">;
npm install 98.css
  • Einzelne Styles wie Button-Abstände oder die Farbe von Eingabe-Labels lassen sich frei neu definieren, ohne die Grundoptik zu verlieren

Grundlegende Auswahl-Controls

  • Buttons

    • Standard-Buttons haben eine Größe von 75×23px, mit erhabenen äußeren und inneren Rahmen sowie einem horizontalen Standardabstand von 12px
    • Unterstützt werden <button>, input[type=submit] und input[type=reset]
    • Die Klasse default kennzeichnet die Standardaktion, die beim Drücken der Enter-Taste im aktiven Fenster ausgeführt wird
    • Beim Klicken wechseln sie in eine gedrückte Darstellung mit eingesenktem Rahmen; deaktivierte Buttons behalten den Rahmen, während das Label ausgegraut wird
    • Der Fokus wird durch einen gestrichelten Rahmen 4px innerhalb des Button-Inhalts angezeigt
  • Checkboxen und Radio-Buttons

    • Checkboxen stehen für unabhängige oder nicht-exklusive Auswahl; im ausgewählten Zustand erscheint ein Häkchen in einem eingesenkten Panel
    • Hinter einer Checkbox ist zwingend ein <label> mit einem for-Attribut nötig, das auf die id des Eingabefelds verweist
    • Über diese Verknüpfung können assistive Technologien die Eingabe korrekt erkennen
    • Unterstützt werden Navigation mit der Tab-Taste und Klicks auf das gesamte Label
    • Auswahl- und Deaktivierungszustände werden über die Standardattribute checked und disabled festgelegt
    • Mehrere Eingaben werden für konsistente Abstände in einen field-row-Container gesetzt
    • Radio-Buttons sind Controls zur Auswahl genau eines Elements aus einer begrenzten Menge und werden mit input[type=radio] erstellt
    • Über das gleiche name-Attribut werden sie zu einer wechselseitig ausschließenden Gruppe zusammengefasst; wie bei Checkboxen werden auch hier Label und field-row verwendet
  • Gruppenfelder

    • fieldset fasst mehrere Controls in einem rechteckigen Rahmen zusammen und erzeugt mit eingesenktem äußerem und erhabenem innerem Rahmen das Aussehen einer gravierten Box
    • Mit einem legend im Inneren lässt sich ein Gruppenlabel anzeigen

Texteingaben und Wertauswahl

  • Textfelder

    • Einzeilige Eingaben bestehen aus input[type=text], mehrzeilige Eingaben aus textarea
    • Eingabe und korrekt verknüpftes Label werden gemeinsam in field-row eingeschlossen und horizontal angeordnet
    • Mit field-row-stacked lässt sich das Label vertikal über dem Eingabeelement platzieren
    • Deaktivierter Zustand und Initialwert werden über die Standardattribute disabled und value von HTML festgelegt
  • Slider

    • Slider stellen einen Anpassungsbereich und den aktuellen Wert dar und werden als input[type=range] gerendert
    • Die Klasse has-box-indicator ersetzt den Standardindikator durch einen kastenförmigen Indikator
    • Wird der Slider in ein div mit der Klasse is-vertical eingeschlossen, kann er vertikal dargestellt werden
    • Die Länge des vertikalen Sliders wird über die Breite des input und die Höhe des umgebenden div angepasst
  • Dropdowns

    • Mit select und option wird ein Dropdown erstellt, in dem ein Element aus einer Liste ausgewählt wird
    • Standardmäßig ist das erste Element ausgewählt; durch das Setzen des Attributs selected auf einer anderen option lässt sich die anfängliche Auswahl ändern

Fenster im Windows-98-Stil

  • Titelleiste

    • Die Titelleiste erstreckt sich über die gesamte Breite am oberen Fensterrand, identifiziert den Inhalt und enthält übliche Fensterbefehls-Buttons
    • Sie besteht aus den drei Klassen title-bar, title-bar-text und title-bar-controls
    • Für das aria-label der Befehls-Buttons können Minimize, Maximize, Restore, Help und Close verwendet werden
    • aria-label übermittelt assistiven Technologien die Absicht des Buttons und wendet zugleich das passende Icon-Styling für den jeweiligen Befehl an
    • Zusätzlich werden eigene Klassen minimize, maximize, restore, help und close bereitgestellt
    • Durch die Trennung von aria-label-Text und visueller Darstellung sollen Mehrsprachigkeit und Lokalisierung keine Rendering- oder Accessibility-Probleme verursachen
    • Bei Fenstern, die nicht maximiert werden können, wird für den Maximize-Button disabled gesetzt
    • Mit title-bar inactive lässt sich unter mehreren Fenstern eine inaktive Titelleiste darstellen
  • Fensterinhalt und Statusleiste

    • Die Klasse window liefert erhabene äußere und innere Rahmen sowie Abstände; über die Breite des Containers lässt sich die Fenstergröße ändern
    • Der eigentliche Inhalt unter der Titelleiste wird in window-body platziert
    • Die Statusleiste am unteren Fensterrand zeigt Kontextinformationen wie aktuellen Status oder Keyboard-Zustand an
    • Für den gesamten Container wird status-bar, für jeden Textbereich status-bar-field verwendet
    • Mit der Statusleiste lassen sich Oberflächen wie Task Manager, Notepad oder File Explorer aufbauen

Hierarchie-, Tab- und Tabellen-Oberflächen

  • Baumansicht

    • ul.tree-view stellt logische Hierarchien zwischen Objekten als eingerückte Liste dar
    • Beim Verschachteln untergeordneter ul werden gestrichelte Rahmen und Einrückungen angewendet; in die enthaltenen li kann beliebiger Inhalt eingefügt werden
    • Auf- und zuklappbare Hierarchien werden erstellt, indem die untergeordnete Liste in ein details-Element eingefügt wird
  • Tabs

    • Die Tab-Liste wird als menu[role=tablist] geschrieben, jeder Tab als li[role=tab]
    • Für den aktiven Tab wird aria-selected="true" gesetzt
    • 98.css enthält keine Logik zum Tab-Wechsel; Zustandsänderungen müssen daher über eigenes JavaScript verwaltet werden
    • Der Tab-Inhalt wird in einem Fensterbereich mit role="tabpanel" platziert
    • Wird menu um die Klasse multirows ergänzt, lassen sich Tabs über mehrere Zeilen erstellen
  • Tabellenansicht

    • Eine HTML-table wird in div.sunken-panel eingebettet, um passende Rahmen und einen scrollbareren Bereich zu erzeugen
    • table.interactive zeigt beim Überfahren von Tabellenzeilen im Body den Mauszeiger als Pointer an
    • Für ausgewählte Zeilen wird die Klasse highlighted verwendet; das eigentliche Zeilenauswahlverhalten muss per separatem Skript implementiert werden

Fortschritt und allgemeine Rahmen

  • Fortschrittsbalken

    • Der Abschlussgrad langer Aufgaben wird dargestellt, indem progress-indicator-bar innerhalb von progress-indicator platziert und über die Breite definiert wird
    • Die Standardform ist ein einfarbiger Balken; mit der Klasse segmented wird er zu einem segmentierten Fortschrittsbalken
  • Feldrahmen

    • Textfelder, Checkboxen, Dropdowns, Spinboxen und Listenfelder verwenden einen Feldstil mit eingesenktem äußeren und inneren Rahmen
    • Normale Felder verwenden innen die Hervorhebungsfarbe von Buttons, schreibgeschützte oder deaktivierte Textfelder dagegen die Button-Oberflächenfarbe
    • Für Statusfelder wird nur ein eingesenkter äußerer Rahmen verwendet; sie eignen sich für Statusleisten oder dynamisch wechselnde schreibgeschützte Inhalte
    • Auch für Arbeitsbereiche außerhalb von Formularen und dynamische Inhalte werden drei allgemeine Klassen bereitgestellt
      • field-border: normaler Arbeitsbereich
      • field-border-disabled: deaktivierter Arbeitsbereich
      • status-field-border: dynamischer Statusinhalt
    • Diese Klassen definieren nur Rahmen, Hintergrundfarbe und minimale Abstände; in der Regel muss daher zusätzliches padding direkt gesetzt werden

Lizenz und Beiträge

  • 98.css wird unter der MIT-Lizenz veröffentlicht
  • Bugs können über GitHub Issues geprüft und gemeldet werden
  • Pull Requests sind willkommen, Code Reviews werden angeboten, und besonders Beiträge von Teilnehmenden, die erstmals zu Open Source beitragen, werden begrüßt

1 Kommentare

 
GN⁺ 3 시간 전
Meinungen auf Hacker News
  • Dieses Projekt entstand im Zuge der Erholung von einem Burnout und liegt mir bis heute besonders am Herzen.
    https://notes.jordanscales.com/98-css-reflections

    • Als Kind habe ich wirklich sehr viel Zeit mit SimGolf verbracht; dann hatte ich es jahrelang vergessen und bekam nach langer Zeit wieder dieses Nostalgiegefühl.
    • Es passte perfekt zu der kleinen Website https://www.mathsheets.net/.
      Die Balance aus Nutzbarkeit und Nostalgie war so gelungen, dass ich es auch in anderen Projekten stärker einsetzen wollte.
    • Beim Erstellen des Winamp-Themes für https://chiptune.app diente 98.css als Ausgangspunkt; es ließ sich sehr leicht anpassen und erweitern.
    • In den letzten Monaten arbeite ich an einer von BeOS inspirierten Retro-CSS-Library: https://beta.mtechnic.me.
      Bei der Recherche bin ich auch auf das Portfolio des 98.css-Autors gestoßen, und sogar unser Musikgeschmack ist völlig gleich. Das ließ mich fragen, ob alle, die Retro-Libraries bauen, ähnliche Vorlieben haben.
    • Die Art der Pflege ist cool: 98.css wird schon lange nicht mehr aktiv selbst weiterentwickelt; stattdessen werden im Repository nur hochwertige Pull Requests geprüft, dann wird sichergestellt, dass der Autor niemand ist, der auf Nutzerrechnern Kryptowährungen minen würde, und anschließend bekommt er volle Commit-Rechte.
  • Flat Design ist lächerlich, hat aber irgendjemandem viel Geld eingebracht, und danach sind alle wie eine Schafherde hinterhergelaufen.
    Dass wir uns nach fast 20 Jahren immer noch nicht davon gelöst haben, überrascht inzwischen auch nicht mehr; wie mehrzeilige Tabs in früheren UIs ganz selbstverständlich funktionierten, war wirklich großartig.

    • Flat oder halbflaches Design kann hervorragend sein, wenn man visuelle Unterscheidungsmerkmale wie Schatten, Konturen und Kontrast sinnvoll einsetzt.
      Die Philosophie „weniger ist mehr“ kollidiert nur mit den übersättigten, spielkneteartigen UIs von Apple, Google und ihren Nachahmern.
    • Wenn es länger dauert, etwas auf einer Seite zu finden, steigt die von Unternehmen geschätzte Verweildauer auf der Seite – so kommt es dann zu Ergebnissen wie heute.
    • Win9x und 3.x hatten an Buttonrändern, Fensterrahmen, Tabs und Textfeldern subtile räumliche Hinweise und Verläufe, wurden mit der Zeit aber immer flacher; inzwischen wirkt es wie eine verlorene Kunst.
    • Das Element, das ich an alten UIs am meisten gehasst habe, waren mehrzeilige Tabs.
      Sie nahmen wertvollen vertikalen Platz ein, wechselten bei jedem Klick die Zeilenposition und sorgten so für Verwirrung; wenn ein Button einen Zustand anzeigt, sollte er sich nach dem Klicken nicht bewegen.
    • Nicht nur Flat Design, auch die Verwendung von Farben wurde reduziert.
      Obwohl wir Monitore und Grafikkarten haben, die Millionen Farben darstellen können, nutzen wir sie nicht aus; es muss nicht wie ein Malbuch aussehen, aber Windows 10 und 11 wirken deprimierend.
  • Was mich bei 98.css und Verwandten immer gestört hat, war, dass MS Sans Serif subtil ungenau ist; am Ende habe ich beschlossen, es selbst zu korrigieren.
    https://github.com/jdan/98.css/pull/230

  • Dieses Projekt war schon früher mehrfach populär: 2024: 471 Punkte, 93 Kommentare https://news.ycombinator.com/item?id=42056918, 2022: 606 Punkte, 182 Kommentare https://news.ycombinator.com/item?id=33310554, 2020: 838 Punkte, 211 Kommentare https://news.ycombinator.com/item?id=22940564

  • Ich würde gern eine Website bauen, auf die dieser Stil passt, aber mir fällt nicht ein, wofür er geeignet wäre.
    Auch XFCE-winxp-tc, das Linux wie Windows XP aussehen lässt, ist großartig. Chicago95 ist weithin bekannt, aber wenn man die Atmosphäre von 2004 möchte, passt https://github.com/rozniak/xfce-winxp-tc sehr gut.

    • Im Internet braucht man keinen passenden Grund; es reicht, es machen zu wollen.
    • Bei XFCE-/GTK-Themes hat mich immer gestört, dass sie zwar behaupten, pixelgenau zu sein, es in Wirklichkeit aber nicht sind.
      Ich weiß nicht, ob das an rechtlichen Bedenken liegt.
  • Die Praxis, deaktivierte Buttons zu entfernen und gar nicht erst anzuzeigen, ist einer der verwirrendsten UI-Trends von heute; graue Buttons beruhigen mich dagegen eher.

    • Microsofts frühere Richtlinien behandelten deaktivierte Controls sehr detailliert.
      Man sollte sie nur deaktivieren, wenn Nutzer erwarten, dass sie anwendbar sind, und den Grund für die Deaktivierung leicht ableiten können; wenn es keine Möglichkeit gibt, sie zu aktivieren, oder Nutzer nicht erwarten, dass sie anwendbar sind, sollte man sie entfernen. Wenn der Grund nicht leicht ersichtlich ist, ist es besser, sie aktiv zu lassen und bei falscher Verwendung eine hilfreiche Fehlermeldung anzuzeigen.
      https://learn.microsoft.com/en-us/windows/win32/uxguide/top-...
      In den modernen Richtlinien https://learn.microsoft.com/en-us/windows/apps/develop/ui/co... werden jedoch weder solche feinen Unterscheidungen noch deaktivierte Buttons selbst behandelt.
    • Funktionen, die Nutzer von vornherein nicht ausführen können, etwa weil ihnen Adminrechte fehlen oder sie nur Leserechte haben, sollte man ausblenden.
      Wenn sie die Berechtigung zur Ausführung haben, es aber wegen des aktuellen Modus oder Zustands nicht möglich ist, sollte man dagegen einen grauen Button anzeigen. In Formularen sollte auch ein grauer Button anklickbar sein und erklären, was falsch ist. Bei einer großen Fluggesellschaft konnte ich wegen fehlender solcher Hinweise den Check-in nicht abschließen.
      Mouseover-Hilfen und kleine ?-Symbole sind verschwunden, und jede Software scheint davon auszugehen, dass man ihre Bedienung vom ersten Tag an kennt.
  • https://ka.ge ist eine mit 98.css erstellte persönliche Website, die unter 1 MB eine Windows-98-Desktopumgebung pixelgenau und tatsächlich funktionsfähig nachbildet.

  • Schade ist, dass die Tabs im Beispiel mit mehrzeiligen Tabs beim Anklicken nicht wie im ursprünglichen Windows zufällig ihre Position ändern.

  • Mit jeder neuen Betriebssystemversion mussten UI-Designer auch funktional unnötige, ressourcenhungrigere, langsamere und instabilere Änderungen als Verbesserungen verkaufen.

    • Beim Ausdruck less faster scheint es, als hätten diese UI-Designer auch an diesem Kommentar mitgewirkt.
  • Ich finde es schwer zu verstehen, warum man sich so auf solche Nachbildungen konzentriert, obwohl die Windows-98-UI nicht einmal der Höhepunkt der User Experience war.
    Die heutige Aufgeblähtheit ist das Ergebnis vieler übereinanderliegender Technik- und Abstraktionsschichten; entscheidend ist daher, zu verstehen, was für eine gute User Experience nötig ist, und die minimalen technischen Bausteine dafür zu finden.

    • Genau genommen war Windows 2000 der Höhepunkt des UI-Designs, danach ging es stetig bergab.
      Runde Ecken und schwebende Abstände sind typische Beispiele, und der Einfluss von macOS und Webdesignern hat der Benutzbarkeit geschadet.