点検チェックシートの最初の版を、HTML・CSS・JavaScript の3つだけ、1つのファイルで作りました。インストールも準備もいりません。ファイルをブラウザで開けば動きます。下で実際に触れます。
点検者を入れて全項目に答えると「記録する」が押せます。油温に 60 と入れると、基準(20〜55℃)を外れているので枠がオレンジに変わります。記録はこのブラウザの中にだけ残ります(設備名・項目・基準値は架空のものです)。
前回は、作るものと、データの形(点検項目のリスト)を決めました。今回はそれを画面にします。
1ファイルの中身
ファイルは index.html 1つ、213行・約7.6KB です。中は3つに分かれています。
| 場所 | 行数 | 役割 |
|---|---|---|
<style> の中(CSS) | 65行 | 色・大きさ・○/× を押したときの見た目 |
<body> の中(HTML) | 26行 | 見出し、点検者の欄、項目を入れる空の入れ物、記録ボタン、履歴の表 |
<script> の中(JavaScript) | 108行 | 項目のリストから画面を作る、判定、保存、履歴の表示 |

HTML がいちばん短いのがポイントです。点検項目そのものは HTML に書かず、JavaScript がリストから作ります。
HTML:入れ物だけ用意する
<label class="who">点検者
<input id="who" autocomplete="name" placeholder="例:山田">
</label>
<ol id="items"></ol>
<button id="save" disabled>記録する</button>
<ol id="items"> は空のままです。ここに JavaScript が項目を1つずつ入れていきます。<label> で入力欄を囲んでおくと、「点検者」という文字を押しても入力欄が選ばれます。スマホでは押せる範囲が広がるので、小さなことですが効きます。
先頭の <meta name="viewport" content="width=device-width, initial-scale=1"> も忘れずに。これがないと、スマホは PC 用の幅で描いて縮小するので、文字もボタンも豆粒になります。
CSS:色を変数にして、状態はクラスで表す
:root {
--accent: #39c5bb; /* 良 */
--navy: #1d2b45;
--ng: #f5a700; /* 否・基準外 */
}
li.item.ok { border-color: var(--accent); }
li.item.ng { border-color: var(--ng); background: #fff8e6; }
色は --accent のような変数にまとめました。色を変えたくなったら1か所直すだけです。
各項目の枠には、答えに応じて ok か ng のクラスが付きます。JavaScript は「この項目は ng」と印を付けるだけで、何色にするかは CSS が決めます。動きと見た目の担当を分けておくと、あとで配色を変えても JavaScript を触らずに済みます。

○/× のボタンは flex: 1 で横いっぱいに2等分し、文字は 20px、上下の余白を 12px 取っています。手袋をしていても押せる大きさにするためです(押しやすさは、のちの回でもう一度見直します)。
JavaScript:リストから画面を作る
前回決めた点検項目のリストを1つずつ取り出し、種類(okng か num)に合わせて部品を作ります。
for (const item of ITEMS) {
const li = document.createElement('li');
li.className = 'item';
li.innerHTML = `<div class="q">${item.q}</div>`;
if (item.type === 'okng') {
// ○ 良 / × 否 のボタンを2つ
} else {
// 「基準:20〜55 ℃」の表示と数値の入力欄
}
ol.appendChild(li);
}

判定は1つの関数にまとめました。○/× なら「良を選んだか」、数値なら「基準の範囲に入っているか」です。
function judge(item, value) {
if (item.type === 'okng') return value === 'ok';
return value >= item.min && value <= item.max;
}
答えが入るたびに、未回答の数を数えてボタンの文字を「記録する(あと 3 項目)」のように変えます。全部答え、点検者も入っていれば押せるようになります。紙では防げなかった書き漏れが、ここで止まります。
保存:localStorage に JSON で
記録は、ブラウザに用意されている小さな保存場所 localStorage に入れます。中身は文字列しか入らないので、JSON.stringify で文字にしてから保存し、読むときに JSON.parse で戻します。
const record = {
at: new Date().toISOString(),
machine: MACHINE,
who: document.getElementById('who').value.trim(),
memo: document.getElementById('memo').value.trim(),
items: ITEMS.map(item => ({ id: item.id, ...answers[item.id] })),
};
const records = loadRecords();
records.push(record);
localStorage.setItem(STORE_KEY, JSON.stringify(records));

保存されるのは、そのブラウザの中だけです。別のスマホからは見えませんし、ブラウザの「サイトデータを削除」で消えます。1台で試すには十分ですが、写真を付けたり長く貯めたりするには向きません。保存のしかたは、のちの回で作り直します。
作っていて気をつけたところ
空欄が「0」として判定される
数値の欄を消して空にしたとき、そのまま Number('') で数値にすると 0 になります。0℃ は基準外なので「異常」と判定され、しかも「回答済み」に数えられてしまいます。空欄のときは、回答を取り消す処理を先に入れました。
const text = e.target.value;
if (text === '') { // 空欄は「未回答」に戻す
delete answers[item.id];
li.classList.remove('ok', 'ng');
update();
return;
}
setAnswer(item, li, Number(text));

スマホで数字のキーボードを出す
数値の欄は type="number" に加えて inputmode="decimal" を付けています。スマホで小数点つきの数字キーボードが出るので、0.52 MPa のような値が打ちやすくなります。
入力された文字は、そのまま HTML にしない
履歴の表に点検者の名前を出すとき、innerHTML に入れずに textContent を使いました。もし名前の欄に <img src=x onerror=...> のような文字が入っていても、ただの文字として表示されます。自分で書いた項目名は innerHTML でもよいのですが、人が入力したものは textContent と決めておくと安心です(セキュリティの回で改めて扱います)。
1ファイルのよいところと、限界
1ファイルは、メールで送っても USB で渡しても、開けば動きます。最初の試作には最適です。一方で、これから機能を足していくと、困ることが出てきます。
- ファイルが長くなり、どこに何があるか探しにくい
- 点検項目のリストを、設備ごとに別のファイルに分けたい
- 人が作った部品(ライブラリ)を借りたい
- 保存するたびにブラウザを手で再読み込みするのが面倒
これを解決するのが、Node.js と npm を中心にした「開発環境」です。
まとめ
- HTML・CSS・JavaScript を1ファイルにまとめれば、準備なしで動くツールが作れる
- HTML は入れ物だけ。項目はデータのリストから JavaScript が作る
- 色は CSS の変数に、状態(良・否)はクラスに。見た目と動きの担当を分ける
- 空欄は 0 ではなく「未回答」。人が入力した文字は textContent で表示する
次回は Node.js と npm を入れて、このツールを「開発環境」に乗せる準備をします。


コメント