98.cssでマルウェアを作る

# はじめに
この記事は、「[CSS Advent Calendar 2024 24日目](https://qiita.com/advent-calendar/2024/cascading_style_sheets)」の記事となります。
さて、クリスマスですね！ 適当に日付を選んだのですが、まさか聖夜となる日にポチっていることに気づいていませんでした... ~~まぁこれもクリぼっちの宿命()~~
タイトルにもあるように「98.cssでマルウェアを作る」ということで嘘みたいなタイトルですが本当です。ただし、ここでのマルウェアはこっちのお話。

https://store.steampowered.com/app/3019370

皆さんはこのゲームを知っていますか？ よくソフトウェアをインストールするときに目的のソフトウェアではないものを追加で入れられそうになったことがあると思います。それらはバンドルウェアなんて言われ、広告や宣伝用途で入っていたり、場合によっては本当のマルウェアだったということもあります。
このゲームは、そんなわかりにくいバンドルウェアをインストールせずに本当のソフトウェアをインストールすることが目的のゲームです。

# What is 98.css?
98.cssは、Windows 98のインタフェースをCSSで再現したライブラリです。

https://jdan.github.io/98.css/#intro

実は2021年ごろから存在はしているみたいですが、最近TLにたまたま流れてきたので興味を持ちました。これと先ほどのゲームを見比べると、皆さんこのように思われることでしょう。
**「あれ、これ使えばマルウェア(ゲーム)作れるんじゃね？」**
と。
どうやらnpmでも使えるようですし、Reactのテンプレートまでご丁寧に用意されているので早速作っていきます。

# 開発環境
今回使うのはこちらのライブラリ・ツールたちです。
- VSCode : こいつがないとなんもできん
- Node.js : 今回は、v20系のNode.jsを使います
- Tailwind CSS : cssファイルを書きたくないのであえて
- 98.css : 今回の主役(1)
- React : 今回の主役(2)
- Next.js : 今回の主役(?)

Next.jsは、Reactを使うために **~~仕方なく~~** 使います。最近v15が出たらしいですが、個人的に使い勝手が悪い[^1]ので慣れているv14にします。

# テンプレ作成
まずはNext.jsのテンプレを生成させておきます。いつも通り`create-next-app`で作ればいいのですが、今回v14のほうを使いたいので、バージョンを指定しておきます。
```shell
npx create-next-app@14 malware
```

# CSSをSCSSに変更
これは好みの話になりますが、自分はCSSファイルを使うよりもSCSSファイルを使うのが好きなので変更します。変更するには、`sass`ライブラリとファイルの変更が必要です。
```
npm i sass
```
でライブラリを先に入れておきます。
次に、`src/app`内のglobals.cssを削除し、`src/assets/css`にstyles.scssを作成します。
srcフォルダ内にassetsフォルダを作り、その中にまたcssフォルダを作っておきます。
styles.scssに、Tailwindお決まりのおまじないを書いておきます。
```scss:styles.scss
@tailwind base;
@tailwind components;
@tailwind utilities;
```
次に、layout.tsxのインポート宣言を修正します。
```diff:layout.tsx
- import "globals.css";
+ import "@/assets/css/styles.scss";
```

# 98.cssをインストール
:::note warn
この方法を用いると、`progress-indicator`など一部のCSSが適用されません。98.cssをインストール後、Githubのリポジトリから最新のCSSをダウンロードし、styles.scssでimportする必要があります。
https://github.com/jdan/98.css/blob/main/style.css
問題のIssueはこちら:
https://github.com/jdan/98.css/issues/212
:::

```
npm i 98.css
```
でインストールし、layout.tsxでインポートします。
```tsx:layout.tsx
import "98.css";
```
最終的にこのようになればOKです。
```tsx:layout.tsx
import type { Metadata } from "next";
import "@/assets/css/styles.scss";
import "98.css";

export const metadata: Metadata = {
  ...
};

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang='ja'>
      <body>{children}</body>
    </html>
  );
}
```

# お試し
早速使ってみるとしましょう。
```tsx:page.tsx
export default function Home() {
  return (
    <div className='p-4 flex gap-3'>
      <button className='default'>Click me!</button>
      <button className='default'>クリック!</button>
    </div>
  );
}

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2467860/072c1712-84b1-3575-49a6-2bed3e89702b.png)
おお...! Windows 98でよく見たUIだ...!

# ウィザードを作る
98.cssのリファレンスにあるCSSを組み合わせるとこうなります。
後ほど完成品とリポジトリを公開しますので詳しくはそちらをご覧ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2467860/f38dcd44-67e9-1218-8a59-d194befc8525.png)

# 完成品
とりあえず完成品を投げておきます。
・リポジトリ

https://github.com/Crysta1221/malware_webapp

・Webサイト

https://malwarewebs.netlify.app/

# 終わりに
今のCSSで、ここまで再現できるとは思っていませんでした。ただ、C#やC++で再現するよりも手軽にできるようになったのはうれしいですね。
この記事は、22日から着手していたのですが何とか間に合いそうですね...(24日、クリぼっちしながらまだ記事を書く羽目にならずに済んだのは少し心が軽くなったような)
今回の方法は、一部無理やり実装していたり、ディレクトリが結構汚くなってしまったので読みにくいかもしれませんが、ある程度のUIの作り方の参考になれば幸いです。
それでは Happy Hacking! :wave:


[^1]: たまーに破壊的変更されるので安定するまで慣れている方を使い続けます