# 98.css - Windows 98 UI를 재현하는 CSS 라이브러리

> Clean Markdown view of GeekNews topic #31768. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=31768](https://news.hada.io/topic?id=31768)
- GeekNews Markdown: [https://news.hada.io/topic/31768.md](https://news.hada.io/topic/31768.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-07-24T20:34:34+09:00
- Updated: 2026-07-24T20:34:34+09:00
- Original source: [jdan.github.io](https://jdan.github.io/98.css/#status-bar)
- Points: 1
- Comments: 1

## Topic Body

- **98.css**는 의미론적 HTML과 접근성을 바탕으로 Windows 98처럼 보이는 웹 인터페이스를 구현하는 CSS 디자인 시스템임
- JavaScript 없이 HTML에 스타일만 적용하므로 **React와 바닐라 JavaScript**를 비롯한 다양한 프런트엔드 환경에서 사용할 수 있음
- 버튼, 입력창, 선택 컨트롤부터 창·탭·트리·표·진행 표시줄까지 폭넓은 **Windows 98 UI 구성요소**를 제공함
- 레이블 연결과 `aria-label`, ARIA 역할을 지원하며, 기본 외형을 유지하면서 여백이나 색상 같은 스타일도 재정의할 수 있음
- unpkg, npm, GitHub Releases로 설치할 수 있고 **MIT 라이선스**로 배포돼 수정과 오픈소스 기여가 가능함

---

### 프로젝트 구성과 설치
- [98.css](https://github.com/jdan/98.css)는 **Windows 98 인터페이스**를 충실하게 재현하는 CSS 라이브러리임
- 의미론적 HTML을 기반으로 버튼에는 `&lt;button&gt;`, 입력 요소에는 `&lt;label&gt;`, 아이콘 버튼에는 `aria-label`을 사용함
- 주요 목표에 **접근성**이 포함되며 키보드 탐색과 보조 기술 사용을 고려함
- JavaScript 없이 CSS로만 HTML을 꾸미므로 특정 프런트엔드 프레임워크에 종속되지 않음
  - [React 사용 예제](https://codesandbox.io/s/objective-chandrasekhar-t5t6h?file=/src/index.js)
  - [바닐라 JavaScript 사용 예제](https://codesandbox.io/s/late-sound-miqho?file=/index.html)
- 가장 빠른 사용법은 unpkg에서 스타일시트를 불러오는 것임

```html
&lt;link rel="stylesheet" href="https://unpkg.com/98.css"&gt;
```

- [GitHub Releases](https://github.com/jdan/98.css/releases)나 [npm](https://www.npmjs.com/package/98.css)으로도 설치할 수 있음

```bash
npm install 98.css
```

- 기본 외형을 유지하면서 버튼 여백이나 입력 레이블 색상 같은 개별 스타일을 자유롭게 재정의할 수 있음

### 기본 선택 컨트롤
- ## 버튼
  - 표준 버튼은 **75×23px** 크기이며 돌출된 외부·내부 테두리와 기본 12px 수평 여백을 가짐
  - `&lt;button&gt;`, `input[type=submit]`, `input[type=reset]`을 지원함
  - `default` 클래스는 활성 창에서 Enter 키를 눌렀을 때 실행할 **기본 동작**을 나타냄
  - 클릭하면 돌출된 테두리가 들어간 형태로 바뀌며, 비활성 버튼은 테두리를 유지한 채 레이블이 흐려짐
  - 포커스는 버튼 콘텐츠 안쪽 4px 위치의 점선 테두리로 표시됨
- ## 체크박스와 라디오 버튼
  - 체크박스는 독립적이거나 비배타적인 선택을 나타내며, 선택되면 들어간 패널 안에 체크 아이콘이 표시됨
  - 체크박스 뒤에는 입력의 `id`를 가리키는 `for` 속성을 가진 **`&lt;label&gt;`이 반드시 필요함**
  - 이 연결을 통해 보조 기술이 입력을 인식할 수 있음
  - Tab 키 탐색과 레이블 전체 클릭을 지원함
  - 표준 `checked`, `disabled` 속성으로 선택 및 비활성 상태를 지정함
  - 여러 입력은 `field-row` 컨테이너로 감싸 일관된 간격을 적용함
  - 라디오 버튼은 제한된 집합에서 하나만 선택하는 컨트롤이며 `input[type=radio]`로 생성함
  - 같은 `name` 속성을 지정해 **상호 배타적 그룹**으로 묶고, 체크박스와 마찬가지로 레이블 및 `field-row`를 사용함
- ## 그룹 상자
  - `fieldset`은 여러 컨트롤을 직사각형 프레임으로 묶고, 들어간 외부 테두리와 돌출된 내부 테두리로 새겨진 상자 같은 모습을 만듦
  - 내부에 `legend`를 배치하면 **그룹 레이블**을 표시할 수 있음

### 텍스트 입력과 값 선택
- ## 텍스트 상자
  - 한 줄 입력은 `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`으로 목록에서 하나의 항목을 선택하는 드롭다운을 만듦
  - 첫 번째 항목이 기본 선택되며, 다른 `option`에 **`selected` 속성**을 지정해 초기 선택을 바꿀 수 있음

### Windows 98 스타일 창
- ## 제목 표시줄
  - 제목 표시줄은 창 상단 전체 너비에 배치돼 내용을 식별하고 일반적인 창 명령 버튼을 포함함
  - `title-bar`, `title-bar-text`, `title-bar-controls` 세 클래스로 구성함
  - 명령 버튼의 `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` 클래스를 추가하면 **분할형 진행 표시줄**로 바뀜
- ## 필드 테두리
  - 텍스트 상자, 체크박스, 드롭다운, 스핀 상자, 목록 상자는 들어간 외부·내부 테두리의 필드 스타일을 사용함
  - 일반 필드는 내부에 버튼 강조 색상을 사용하고, 읽기 전용 또는 비활성 텍스트 필드는 버튼 표면 색상을 사용함
  - 상태 필드에는 들어간 외부 테두리만 적용하며, 상태 표시줄이나 동적으로 바뀌는 읽기 전용 콘텐츠에 활용함
  - 폼 이외의 작업 영역과 동적 콘텐츠에도 사용할 수 있도록 세 가지 범용 클래스를 제공함
    - `field-border`: 일반 작업 영역
    - `field-border-disabled`: 비활성 작업 영역
    - `status-field-border`: 동적 상태 콘텐츠
  - 이 클래스들은 테두리, 배경색, 최소 여백만 정의하므로 보통 **추가 `padding`** 을 직접 지정해야 함

### 라이선스와 기여
- 98.css는 [MIT 라이선스](https://github.com/jdan/98.css/blob/main/LICENSE)로 배포됨
- 버그 확인과 신고는 [GitHub Issues](https://github.com/jdan/98.css/issues)에서 할 수 있음
- 풀 리퀘스트를 받고 코드 리뷰를 제공하며, 특히 오픈소스에 처음 기여하는 참여자를 환영함

## Comments



### Comment 62333

- Author: neo
- Created: 2026-07-24T20:34:35+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=49028927) 
- 이 프로젝트는 **번아웃 회복 과정**에서 만든 것으로, 지금도 각별하게 아끼고 있음  
  [https://notes.jordanscales.com/98-css-reflections](https://notes.jordanscales.com/98-css-reflections)
  - 어릴 때 **SimGolf**에 정말 많은 시간을 썼는데 몇 년간 잊고 있다가 오랜만에 향수를 느꼈음
  - 작은 웹사이트 [https://www.mathsheets.net/](https://www.mathsheets.net/)에 완벽하게 어울렸음  
    사용성과 향수의 균형이 절묘해서 다른 프로젝트에도 더 활용하고 싶어짐
  - [https://chiptune.app](https://chiptune.app/)의 **Winamp 테마**를 만들 때 98.css를 출발점으로 삼았으며, 수정하고 확장하기가 매우 쉬웠음
  - 지난 몇 달간 **BeOS에서 영감을 받은 복고풍 CSS 라이브러리** [https://beta.mtechnic.me](https://beta.mtechnic.me/)를 만들고 있음  
    조사하다가 98.css 제작자의 포트폴리오도 발견했는데 음악 취향까지 완전히 같아서, 복고풍 라이브러리를 만드는 이들이 모두 비슷한 취향인지 궁금해졌음
  - 98.css를 오래전부터 직접 개발하지 않고, 저장소에서 양질의 풀 리퀘스트만 살펴본 뒤 작성자가 사용자 컴퓨터에서 암호화폐를 채굴할 사람은 아닌지 확인하고 **전체 커밋 권한**을 준다는 관리 방식이 멋짐

- **플랫 디자인**은 우스꽝스러운데도 누군가에게 큰돈을 벌어준 뒤 모두가 양 떼처럼 따르고 있음  
  거의 20년이 지나도록 벗어나지 못한 것도 이제 놀랍지 않으며, 예전 UI에서 여러 줄 탭이 자연스럽게 작동하던 방식은 정말 훌륭했음
  - 플랫 또는 준플랫 디자인은 그림자·윤곽선·대비 같은 **시각적 구분 요소**를 적절히 쓰면 훌륭함  
    적을수록 좋다는 철학이 Apple·Google과 그 모방자들의 과포화된 장난감 점토 같은 UI와 충돌할 뿐임
  - 페이지에서 무언가를 찾는 시간이 길어지면 기업이 중시하는 **페이지 체류 시간**이 늘어나니 지금 같은 결과가 나온 셈임
  - Win9x와 3.x에는 버튼 가장자리, 창 테두리, 탭, 텍스트 상자에 미묘한 **입체 단서**와 그라데이션이 있었지만 시간이 흐르며 계속 평평해졌고, 이제는 잃어버린 기술처럼 보임
  - 예전 UI에서 가장 싫었던 요소가 여러 줄 탭이었음  
    귀중한 세로 공간을 차지하고 클릭할 때마다 줄의 위치가 바뀌어 혼란스러웠으며, 상태를 나타내는 버튼이라면 클릭 후 움직여서는 안 됨
  - 플랫 디자인뿐 아니라 **색상 사용**까지 줄어들었음  
    수백만 색상을 표시할 모니터와 그래픽카드를 갖고도 활용하지 않으며, 색칠 공부처럼 만들 필요는 없지만 Windows 10과 11은 우울하게 느껴짐

- 98.css 계열에서 늘 거슬렸던 부분은 **MS Sans Serif가 미묘하게 부정확하다**는 것이었고, 결국 직접 수정하기로 했음  
  [https://github.com/jdan/98.css/pull/230](https://github.com/jdan/98.css/pull/230)

- 이 프로젝트는 이전에도 여러 차례 인기를 끌었음: **2024년 471점·댓글 93개** [https://news.ycombinator.com/item?id=42056918](https://news.ycombinator.com/item?id=42056918), **2022년 606점·댓글 182개** [https://news.ycombinator.com/item?id=33310554](https://news.ycombinator.com/item?id=33310554), **2020년 838점·댓글 211개** [https://news.ycombinator.com/item?id=22940564](https://news.ycombinator.com/item?id=22940564)
  - 지난번에도 호응이 좋았던 **복고풍 CSS 모음**임  
    Windows 95: [https://alexbsoft.github.io/win95.css/](https://alexbsoft.github.io/win95.css/), 1980년대 웹사이트: [https://bootstra386.com/](https://bootstra386.com/), Windows XP: [https://botoxparty.github.io/XP.css/](https://botoxparty.github.io/XP.css/), GeoCities: [https://code.divshot.com/geo-bootstrap/](https://code.divshot.com/geo-bootstrap/), Counter-Strike 1.6: [https://cs16.samke.me/](https://cs16.samke.me/), Edward Tufte: [https://edwardtufte.github.io/tufte-css/](https://edwardtufte.github.io/tufte-css/), Windows 98: [https://jdan.github.io/98.css/](https://jdan.github.io/98.css/), Windows 7: [https://khang-nd.github.io/7.css/](https://khang-nd.github.io/7.css/), PlayStation: [https://micah5.github.io/PSone.css/](https://micah5.github.io/PSone.css/), NES: [https://nostalgic-css.github.io/NES.css/](https://nostalgic-css.github.io/NES.css/), Apple System: [https://sakofchit.github.io/system.css/](https://sakofchit.github.io/system.css/), SNES: [https://snes-css.sadlative.com/](https://snes-css.sadlative.com/), The Sims: [https://thesimscss.inbn.dev/](https://thesimscss.inbn.dev/)
  - 다음 재등장은 **2028년**일 듯함

- 이 스타일을 적용할 웹사이트를 만들고 싶지만 어디에 어울릴지 떠오르지 않음  
  Linux를 Windows XP처럼 꾸며 주는 **XFCE-winxp-tc**도 훌륭함. Chicago95는 많이 알려졌지만 2004년 분위기를 원한다면 [https://github.com/rozniak/xfce-winxp-tc](https://github.com/rozniak/xfce-winxp-tc/)가 잘 맞음
  - 인터넷에서는 어울릴 이유가 필요 없고, **하고 싶다는 마음**만 있으면 됨
  - XFCE·GTK 테마들은 픽셀 단위로 정확하다고 내세워도 실제로는 그렇지 않다는 점이 늘 불만이었음  
    법적 우려 때문에 그런지는 모르겠음

- 비활성화된 버튼을 없애고 아예 표시하지 않는 방식은 오늘날 가장 혼란스러운 **UI 추세** 중 하나이며, 회색 버튼을 보면 오히려 마음이 편해짐
  - Microsoft의 예전 지침은 **비활성화된 컨트롤**을 세밀하게 다뤘음  
    사용자가 적용 가능하다고 예상하고 비활성화 이유를 쉽게 추론할 수 있을 때만 끄고, 활성화할 방법이 없거나 적용될 것으로 예상하지 않는다면 제거해야 함. 이유를 쉽게 알기 어렵다면 활성 상태로 두고 잘못 사용했을 때 유용한 오류 메시지를 보여주는 편이 나음  
    [https://learn.microsoft.com/en-us/windows/win32/uxguide/top-...](https://learn.microsoft.com/en-us/windows/win32/uxguide/top-violations#:~:text=Reconsider%20disabled%20controls,disable%20the%20control.)  
    하지만 현대 지침 [https://learn.microsoft.com/en-us/windows/apps/develop/ui/co...](https://learn.microsoft.com/en-us/windows/apps/develop/ui/controls/buttons)에서는 이런 미묘한 구분은 물론 비활성화 버튼 자체도 다루지 않음
  - 관리자 권한이 없거나 보기 권한만 있는 것처럼 사용자가 애초에 실행할 수 없는 기능은 버튼을 숨기는 편이 맞음  
    반면 실행 권한은 있지만 현재 모드나 상태 때문에 불가능하다면 **회색 버튼**을 보여줘야 함. 폼에서는 회색 버튼도 클릭할 수 있게 하고 무엇이 잘못됐는지 알려줄 필요가 있음. 한 대형 항공사에서는 이런 안내가 없어 체크인을 완료하지 못했음  
    마우스 올림 도움말과 작은 `?` 표시는 사라졌고, 모든 소프트웨어가 첫날부터 사용법을 안다고 가정하는 듯함

- [https://ka.ge](https://ka.ge/)는 98.css로 만든 개인 사이트로, **1MB 미만**에서 Windows 98 데스크톱 환경을 픽셀 단위로 정확하고 실제 작동하게 재현했음

- 여러 줄 탭 예제의 탭이 클릭할 때 원래 Windows처럼 **무작위로 위치를 바꾸지 않는 것**은 아쉬움

- 운영체제 새 버전마다 UI 디자이너는 기능적으로 불필요하고 자원을 더 쓰며 느리고 불안정한 변경도 **개선이라고 포장**해야 했음
  - `less faster`라는 표현을 보니 그 UI 디자이너들이 이 댓글에도 손댄 듯함

- Windows 98 UI가 사용자 경험의 정점도 아닌데 이런 재현 작업에 집중하는 이유를 이해하기 어려움  
  오늘날의 비대함은 기술과 **추상화 계층**이 겹겹이 쌓인 결과이므로, 좋은 사용자 경험에 필요한 요소를 이해하고 최소한의 기술 구성요소를 찾는 것이 핵심임
  - 정확히는 **Windows 2000이 UI 디자인의 정점**이었고 이후 계속 나빠졌음  
    둥근 모서리와 떠 있는 여백이 대표적이며, macOS와 웹 디자이너의 영향은 사용성을 해쳤음
