- 98.css permite criar interfaces web com aparência de Windows 98 usando apenas CSS, recriando fielmente a UI clássica de desktop
- A acessibilidade depende de HTML semântico, partindo do uso correto de atributos ARIA em botões, rótulos e botões de ícone
- Como não inclui JavaScript, pode ser usado independentemente do framework em projetos com React, JavaScript puro ou HTML comum
- Oferece componentes no estilo Windows 98 como botões, checkboxes, botões de opção, janelas, tree view, abas, table view e barras de progresso
- Pode ser usado via npm, GitHub Releases ou unpkg e é distribuído sob a licença MIT, recebendo relatos de bugs e pull requests
Como a UI do Windows 98 é recriada com CSS
- 98.css é uma biblioteca CSS para criar interfaces com aparência de Windows 98
- O projeto pode ser conferido no GitHub
- A acessibilidade depende da estrutura semântica em HTML, e não de scripts separados
- Botões devem usar
<button>
- Elementos de entrada precisam de um
<label> correspondente
- Botões de ícone devem transmitir sua intenção com
aria-label
- É possível sobrescrever parte do estilo dos elementos mantendo a aparência básica
- Dá para aumentar o padding dos botões ou adicionar cor aos rótulos de inputs
Instalação e integração com frameworks
- 98.css aplica o estilo do Windows 98 a elementos HTML apenas com CSS, sem JavaScript
- Pode ser usado de forma independente de frameworks frontend
- Há exemplos de uso com React e com JavaScript puro
- A forma mais rápida de usar é importar a stylesheet via unpkg
<link rel="stylesheet" href="https://unpkg.com/98.css">
npm install 98.css
Controles básicos de formulário
-
Button
- O botão padrão tem largura de 75px, altura de 23px, bordas externa e interna em relevo e padding horizontal padrão de 12px
- Ao adicionar a classe
default, é possível indicar visualmente a ação padrão executada pela tecla Enter no Windows 98
- No estado clicado, a borda em relevo muda para uma aparência pressionada
- Botões desativados mantêm a mesma borda em relevo, mas o rótulo aparece esmaecido
- O foco é mostrado com uma borda pontilhada a 4px para dentro do conteúdo do botão
-
Checkbox
- Checkboxes representam seleções independentes ou não mutuamente exclusivas
- Quando selecionado, um ícone de marcação aparece dentro de um painel rebaixado, com um rótulo ao lado representando a opção
- Deve-se incluir um
<label> após <input type="checkbox">, com o atributo for apontando para o id do input
- Os atributos
checked e disabled podem ser usados
- Ao agrupar vários inputs, cada um deve ser envolvido em um contêiner com a classe
field-row para alinhar o espaçamento
-
Option Button
- Botões de opção são controles em que apenas uma alternativa pode ser escolhida entre opções limitadas
- São usados com
<input type="radio"> e, ao compartilhar o mesmo atributo name, formam um grupo
- Assim como os checkboxes, podem ser envolvidos com
field-row para manter espaçamento consistente entre inputs
- Suportam os atributos
checked e disabled
-
Group Box
- A group box é uma moldura retangular usada para organizar vários controles
- É usada envolvendo elementos com
fieldset, oferecendo borda externa rebaixada e borda interna em relevo
- É possível adicionar um rótulo de grupo colocando
legend dentro de fieldset
Entrada de texto, slider e dropdown
-
TextBox
- A caixa de texto é um controle retangular em que o usuário pode inserir ou editar texto
- Entradas de uma única linha são renderizadas com
<input type="text">
- Recomenda-se fornecer um
<label> correspondente com o atributo for correto, envolvendo ambos em um contêiner field-row
- Com a classe
field-row-stacked, o rótulo pode ficar acima do input em vez de ao lado
- Para entradas de várias linhas, usa-se
textarea
- Atributos HTML padrão como
disabled e value podem ser usados
-
Slider
- O slider é composto por uma barra que representa a faixa de ajuste e um indicador que mostra o valor atual
- É renderizado com
<input type="range">
- A classe
has-box-indicator permite trocar o indicador padrão por um indicador em formato de caixa
- Ao envolvê-lo em uma
div com is-vertical, ele pode ser exibido como slider vertical
- Para mudar o comprimento do slider vertical, é preciso ajustar a largura do
input e a altura da div
-
Dropdown
- A caixa de lista suspensa permite selecionar apenas um item de uma lista
- No estado fechado, mostra o valor atual, e o usuário abre a lista para mudar esse valor
- É renderizada com os elementos
select e option
- O padrão é a primeira opção; para alterar a seleção inicial, basta usar
selected em um option específico
Montando janelas no estilo Windows 98
-
Title Bar
- A barra de título fica na borda superior interna da janela e identifica seu conteúdo
- É composta pelas classes
title-bar, title-bar-text e title-bar-controls
- O botão de fechar usa
aria-label="Close" para transmitir sua intenção a tecnologias assistivas
- Também é possível usar
aria-label como Minimize, Maximize, Restore e Help
- Cada
aria-label tem uma classe de estilo correspondente, evitando problemas de renderização, acessibilidade e localização mesmo quando o texto do aria-label estiver em outro idioma
- O botão de maximizar pode ser desativado com
disabled
- Ao adicionar a classe
inactive, a barra de título pode aparecer como inativa
-
Window contents
- A classe
window cria o contêiner da janela onde entra a barra de título, oferecendo bordas externa e interna em relevo e padding
- É possível definir a largura no estilo do contêiner para ajustar livremente o tamanho da janela
- O conteúdo abaixo da barra de título pode ser desenhado com a classe
window-body
-
Status Bar
- A barra de status normalmente fica na parte inferior da janela e mostra informações de estado atual ou de contexto
- É renderizada com a classe
status-bar
- Cada elemento de texto deve usar a classe
status-bar-field
- O exemplo inclui campos de status como
Press F1 for help, Slide 1 e CPU Usage: 14%
Listas, abas, tabelas e indicador de progresso
-
TreeView
- A tree view é uma caixa de lista especial que mostra um conjunto de objetos em forma de estrutura hierárquica recuada
- É renderizada aplicando a classe
tree-view a um elemento ul
- Os elementos
li filhos podem conter qualquer conteúdo desejado
- Ao incluir
ul aninhados, a estrutura em árvore é exibida com bordas pontilhadas e recuo
- Seções expansíveis podem ser criadas colocando a lista filha dentro de um elemento
details
-
Tabs
- O controle de abas é usado para definir várias páginas lógicas ou seções de informação dentro da mesma janela
- Aplica-se
role="tablist" ao elemento menu, e role="tab" aos elementos li filhos
- O gerenciamento das abas deve ser feito com código JavaScript do usuário
- Para a aba ativa, basta adicionar
aria-selected="true"
- Abas em várias linhas podem ser criadas adicionando a classe
multirows à tag menu
-
TableView
- A table view é renderizada com o elemento
table
- Para fornecer bordas adequadas e um contêiner com overflow, ela deve ser envolvida por uma
div com a classe sunken-panel
- Com um pouco de script adicional, a table view pode se tornar interativa
- Se a classe
interactive for aplicada à table, o cursor de ponteiro aparece ao passar o mouse sobre linhas do corpo
- Se uma linha receber a classe
highlighted, ela parecerá selecionada
-
Progress Indicator
- A barra de progresso é usada para mostrar a porcentagem de conclusão de uma tarefa longa
- O padrão é uma barra de progresso sólida
- Com a classe
segmented, é possível declarar uma barra de progresso segmentada
- O progresso é indicado pelo estilo
width de progress-indicator-bar
Bordas de campo e participação em open source
-
Field borders
- Caixas de texto, checkboxes, caixas de lista suspensa, spin boxes e list boxes usam o estilo de borda de campo
- A área de trabalho dentro de janelas também pode usar esse mesmo estilo
- As bordas de campo usam borda externa rebaixada e borda interna rebaixada
- O interior da maioria dos controles usa a cor de destaque de botão
- Quando campos de texto como text boxes e combo boxes estão em modo somente leitura ou desativados, o interior usa a cor de face do botão
- Para uso geral, são fornecidas as classes
field-border, field-border-disabled e status-field-border
- Essas classes definem apenas borda, cor de fundo e padding mínimo, então normalmente é preciso ajustar padding adicional manualmente
-
Licença e contribuição
- 98.css é um projeto sob licença MIT
- A verificação e o relato de bugs são feitos na página de issues do GitHub
- Pull requests são bem-vindos, e o projeto afirma oferecer code review especialmente para quem está começando a participar de open source
- O objetivo do projeto é ser um espaço para adquirir experiência divertida com open source
1 comentários
Opiniões no Hacker News
Criei algo parecido que inclui 3.11, 95, 2000, XP, CDE, Mac OS 9 e todas as respectivas paletas de cores padrão: https://nielssp.github.io/classic-stylesheets/?theme=win9x&s...
O foco não era uma reprodução perfeita no nível de pixel, mas sim uma forma que funcionasse bem e tivesse boa aparência mesmo em ambientes modernos, como monitores de alta resolução.
Por isso recriei todos os ícones e símbolos em SVG e, quando adicionei XP e Mac OS 9, publiquei no Show HN, mas não recebeu muita atenção.
Pessoalmente, o Windows 2000 foi o auge do design de UI.
Algo que eu gostaria de ver a mais seria um tema para tabelas de dados, e seria ótimo ter também tabelas interativas que funcionassem como listas e grades.
https://nielssp.github.io/classic-stylesheets/?theme=win3x&s...
Sou o criador. Fico feliz em ver isso aparecer de novo.
Este foi meu projeto de recuperação de burnout, e recentemente escrevi algumas reflexões relacionadas: https://notes.jordanscales.com/98-css-reflections
[0]: https://www.mathsheets.net/
É interessante como a computação retrô, como jogos antigos ou sistemas operacionais antigos, pode ser reconfortante e até terapêutica.
Senti algo parecido ao jogar no emulador jogos de Gameboy e Nintendo da infância, ou ao rodar o Macintosh System 9, e também me vêm à mente Pico-8, SerenityOS e TempleOS.
Eles têm em comum ambientes de computação retrô que o usuário consegue entender e controlar completamente, e deve haver também uma dinâmica psicológica mais profunda, como uma sandbox segura enquanto ferramenta terapêutica.
Hoje há tantos dark patterns hostis na tecnologia e na sociedade que encontrar espaços físicos e mentais projetados para o conforto do usuário é um grande alívio.
Seria bom ter também versões para Windows 2000 e Windows XP.
Coisas que reuni:
The Sims https://thesimscss.inbn.dev/
Windows 98 https://jdan.github.io/98.css/
Windows XP https://botoxparty.github.io/XP.css/
Windows 7 https://khang-nd.github.io/7.css/
Edward Tufte https://edwardtufte.github.io/tufte-css/
O 98.css virou um clássico do HN por bons motivos.
Discussões anteriores:
https://news.ycombinator.com/item?id=33310554 - outubro de 2022, 179 comentários
https://news.ycombinator.com/item?id=22940564 - abril de 2020, 211 comentários
Também vale ver o HyperCard Simulator e o Decker.
https://hn.algolia.com/?q=hypercard
Lembro que, no fim dos anos 90, a Microsoft tinha nomes de cores embutidos no CSS que se ajustavam ao tema e às cores da área de trabalho do Windows.
Não sei se ainda funcionam; na IDE aparecem todos em vermelho, então parecem não funcionar.
Dava para usar valores como
windowtext,appworkspace,menutext,threedlightshadow,threedshadow,threedfacepara criar uma UI web que combinasse com o look and feel da área de trabalho do usuário.Usei isso em 1998 em um app de intranet baseado em navegador, e assim ele parecia um pouco mais nativo.
https://drafts.csswg.org/css-color/#css-system-colors
As cores antigas foram todas marcadas como obsoletas:
https://drafts.csswg.org/css-color/#deprecated-system-colors
Este estilo não combina bem com DPI não padrão
Por exemplo, se você definir a escala do monitor em 150%, para tentar alinhar aos pixels físicos, dá para executar algo assim no console do navegador:
with(document.documentElement.style){ transform = \scale(${ 1 / devicePixelRatio })`; transformOrigin = 'top left'; }`Multiplicar a escala por um número inteiro dá uma sensação de ampliação nítida e, mesmo que não fique 100% perfeito, parece muito mais próximo da renderização pretendida
withdesse jeito é meio assustador e, ao mesmo tempo, muito refrescanteGosto e detesto ao mesmo tempo
Parece que usaram um pouco disso no crowdwave: https://www.crowdwave.com
Também vale ver: https://botoxparty.github.io/XP.css e https://khang-nd.github.io/7.css
Hoje em dia virou quase um mantra que é preciso haver espaço para respirar, como entre as opções de um grupo de botões de rádio, mas o espaçamento apertado das UIs antigas parece mais honesto, mais respeitoso com o usuário final e com maior densidade de informação
Não quero abrir mão de todas as inovações, mas muitas vezes sinto falta das UIs antigas
Eu não gostava da decoração das janelas do Windows 7, mas o resto não ficaria ruim em apps Electron
A UI do Windows XP foi a melhor entre todas as UIs do Windows: moderna o suficiente para parecer elegante, mas ainda com contraste, fácil de ver, ler e entender
A UI do Windows 7 era chamativa demais e priorizava a aparência em vez da legibilidade, enquanto o Windows 98 era antigo demais, cinza demais e também sofria com falta de contraste
https://git.sr.ht/~q3cpma/website/tree/master/item/src/resou...
https://world-playground-deceit.net/
Ver coisas assim dá vontade de levar até o fim
Só de olhar, não parece ser a MS Sans Serif que era renderizada no Windows 95 e no Windows 98
https://web.archive.org/web/20230603234837/https://vistaserv...
A folha de estilos de XP[1] linkada em outro comentário desenha texto e formas em alta resolução, reduzindo as limitações enquanto mantém a sensação da UI
O motivo de eu gostar de UIs como a do 98 não é a baixa resolução, e sim a clareza e simplicidade
[1] https://news.ycombinator.com/item?id=42056921
Acho isso muito melhor do que o que saiu de anos de “pesquisa” e “melhorias” em UX/UI
Eu tinha um ano em 1998, então não é por eu ser de uma geração antiga
Só detesto botões que não parecem botões, abas que não parecem abas e campos de texto em que você só descobre que dá para editar depois de clicar
A Apple provavelmente pesquisou um pouco para o MacOSX, mas nos últimos 20 anos, especialmente no mobile, a sensação é que os recursos foram simplesmente jogados ali, sem noções de descoberta ou consistência
Acima de tudo, parece que muitas das causas dos problemas foram as empresas quererem “branding consistente” ou uma “aparência própria”
E esse site também tem um botão “show code” disfarçado de texto comum