ブラウザだけで動く
「ラーメンタイマー」の作り方

HTML・CSS・JavaScriptを1つのファイルへまとめ、3分・4分・5分・7分を選べるタイマーを作ります。画面は出るのにボタンが動かない理由や、URLから使える状態へ公開する方法まで、初心者向けに順番に解説します。

最初に結論:簡単なWebタイマーは、HTMLで画面、CSSで見た目、JavaScriptで動きを作れば完成します。パソコン内で試すだけならHTMLファイル1つで十分です。ほかの端末からURLで使うには、完成したファイルをWebサーバーへ配置します。

まずは完成版を触ってみましょう

時間を選び、「スタート」を押すとカウントダウンが始まります。

🍜 ラーメンタイマーを今すぐ使う

今回作るもの

アプリの追加インストールなしで、ChromeやSafariから使えるラーメンタイマーです。

  • 3分・4分・5分・7分の時間選択
  • スタート、一時停止、再開、リセット
  • 残り時間を「03:00」の形で表示
  • 終了時の音と振動(対応端末)
  • 画面を閉じた間も、時刻差から残り時間を補正
  • スマートフォンでも押しやすいボタン

最初から全部を覚える必要はありません。まず基本のカウントダウンを作り、動作を確認してから機能を足すと理解しやすくなります。

実際の公開画面を3枚で確認

トップページの導線からタイマーを開くまでを、実際の画面に沿って確認します。

  1. トップ画面へラーメンタイマー導線を追加

    Tech Beginner Guideのトップ画面に、既存のデザインに合わせた「🍜 ラーメンタイマー」ボタンを追加しました。「知りたいことを探す」「カテゴリーから探す」と並ぶため、初めて訪れた人でも見つけやすくなります。

    Tech Beginner Guideのトップ画面にラーメンタイマーへの導線ボタンを追加した様子
    ① サイトのトップ画面に「🍜 ラーメンタイマー」への導線を追加した状態。
  2. 押す場所が分かる大きな導線ボタン

    ボタンは文字だけのリンクではなく、指でも押しやすい大きさにしています。ラーメンの絵文字と機能名を組み合わせ、リンク先が一目で分かるようにしました。

    知りたいことを探す、カテゴリーから探すの下にあるラーメンタイマー導線ボタンの拡大表示
    ② 導線ボタンの拡大。ほかの操作ボタンと同じ角丸・余白で、既存デザインになじませています。
  3. 完成した赤いラーメンタイマーを表示

    導線を押すと、赤い背景のタイマー画面が開きます。時間選択、残り時間、スタート、リセットを1画面に集め、調理中でも迷いにくい構成です。

    赤い背景に3分・4分・5分・7分の選択、03:00の残り時間、スタートとリセットを表示したラーメンタイマー完成画面
    ③ 完成した赤いラーメンタイマー。3分・4分・5分・7分を選び、スタートまたはリセットできます。

Webアプリは3つの技術で作れる

HTMLボタン、数字、見出しなど、画面の構造を作ります。
CSS色、余白、文字サイズ、スマホ表示など見た目を整えます。
JavaScriptボタンを押した時の処理と、1秒ずつ減る動きを作ります。

ラーメン店に例えるなら、HTMLが店舗、CSSが内装、JavaScriptが店員さんの動きです。3つを同じHTMLファイルへ書けば、最初の練習ではファイル管理も簡単です。

1ファイルで動く基本コード

次の内容をコピーし、ramen-timer.htmlという名前で保存します。

学習しやすいように基本機能へ絞ったコードです。公開中の完成版は、ここへ音・振動・画面復帰時の時間補正を追加しています。

ramen-timer.html
<!doctype html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0">
  <title>ラーメンタイマー</title>
  <style>
    * { box-sizing: border-box; }
    body {
      margin: 0;
      min-height: 100vh;
      display: grid;
      place-items: center;
      padding: 20px;
      font-family: system-ui, sans-serif;
      background: repeating-linear-gradient(
        45deg, #e43d2f 0 18px, #d83227 18px 36px
      );
    }
    .timer {
      width: min(100%, 520px);
      padding: 28px 20px;
      text-align: center;
      background: #fff9e8;
      border: 5px solid #24140d;
      border-radius: 28px;
      box-shadow: 0 16px 45px #0006;
    }
    h1 { margin: 0 0 12px; }
    #time {
      margin: 20px 0;
      font-size: clamp(70px, 20vw, 108px);
      line-height: 1;
      font-weight: 900;
      font-variant-numeric: tabular-nums;
    }
    .presets, .controls {
      display: flex;
      justify-content: center;
      flex-wrap: wrap;
      gap: 10px;
      margin-top: 14px;
    }
    button {
      min-height: 48px;
      padding: 12px 18px;
      border: 3px solid #24140d;
      border-radius: 14px;
      background: #fff1c8;
      font-size: 17px;
      font-weight: 900;
      cursor: pointer;
      box-shadow: 0 4px 0 #24140d;
    }
    button:active {
      transform: translateY(4px);
      box-shadow: none;
    }
    .start { background: #c92720; color: #fff; }
    .active { background: #f4b942; }
    #status { min-height: 28px; margin-top: 18px; font-weight: 800; }
  </style>
</head>
<body>
  <main class="timer">
    <h1>🍜 麺、まもなく。</h1>
    <div id="time">03:00</div>

    <div class="presets">
      <button class="preset active" data-seconds="180">3分</button>
      <button class="preset" data-seconds="240">4分</button>
      <button class="preset" data-seconds="300">5分</button>
      <button class="preset" data-seconds="420">7分</button>
    </div>

    <div class="controls">
      <button class="start" id="start">▶ スタート</button>
      <button id="reset">↻ リセット</button>
    </div>
    <div id="status">お湯を入れたらスタート!</div>
  </main>

  <script>
    let selected = 180;
    let remaining = selected;
    let timerId = null;

    const time = document.querySelector("#time");
    const start = document.querySelector("#start");
    const reset = document.querySelector("#reset");
    const status = document.querySelector("#status");

    function draw() {
      const minutes = Math.floor(remaining / 60);
      const seconds = remaining % 60;
      time.textContent =
        String(minutes).padStart(2, "0") + ":" +
        String(seconds).padStart(2, "0");
    }

    document.querySelectorAll(".preset").forEach((button) => {
      button.addEventListener("click", () => {
        clearInterval(timerId);
        timerId = null;
        selected = Number(button.dataset.seconds);
        remaining = selected;
        document.querySelectorAll(".preset").forEach((item) => {
          item.classList.remove("active");
        });
        button.classList.add("active");
        start.textContent = "▶ スタート";
        status.textContent = button.textContent + "にセットしました";
        draw();
      });
    });

    start.addEventListener("click", () => {
      if (timerId !== null) {
        clearInterval(timerId);
        timerId = null;
        start.textContent = "▶ 再開";
        status.textContent = "一時停止中";
        return;
      }

      if (remaining === 0) remaining = selected;
      start.textContent = "⏸ 一時停止";
      status.textContent = "最高の一杯まで、あと少し…";

      timerId = setInterval(() => {
        remaining--;
        draw();
        if (remaining <= 0) {
          clearInterval(timerId);
          timerId = null;
          remaining = 0;
          draw();
          start.textContent = "▶ もう一杯";
          status.textContent = "🍜 できあがり!";
        }
      }, 1000);
    });

    reset.addEventListener("click", () => {
      clearInterval(timerId);
      timerId = null;
      remaining = selected;
      start.textContent = "▶ スタート";
      status.textContent = "お湯を入れたらスタート!";
      draw();
    });

    draw();
  </script>
</body>
</html>
ファイル名に注意:テキストエディタによっては、末尾へ自動で.txtが付く場合があります。ramen-timer.html.txtではなく、必ずramen-timer.htmlにします。

Macで動かしてみる

  1. 標準テキストで編集する:テキストエディットを使う場合は「フォーマット」から「標準テキストにする」を選びます。Visual Studio Codeなどのコードエディタでも構いません。
  2. HTMLとして保存する:上のコードを貼り付け、文字コードをUTF-8にしてramen-timer.htmlで保存します。
  3. ブラウザで開く:保存したファイルをChromeやSafariへドラッグすると、タイマー画面が表示されます。
  4. ボタンを試す:4分や5分へ切り替え、スタート、一時停止、再開、リセットを順に確認します。

URL欄にfile:///Users/ユーザー名/...と表示されるのは、インターネット上ではなく、Mac内のファイルをブラウザが直接読んでいるためです。

画面は出るのにボタンが動かない理由

見た目を担当するHTML・CSSが正常でも、JavaScriptに問題があるとボタンだけ反応しません。

idの名前が一致しているか

JavaScriptのdocument.querySelector("#start")は、HTMLからid="start"の要素を探します。HTML側がid="startButton"なら、同じ名前へそろえる必要があります。

JavaScriptを置く位置

ボタンが読み込まれる前にJavaScriptを実行すると、対象を見つけられない場合があります。初心者は、上のコードのように<script></body>の直前へ置くと分かりやすいでしょう。

記号の入力ミス

半角の引用符、丸かっこ、波かっこが1つ欠けるだけでも、その後の処理が止まります。Chromeでは開発者ツールの「Console」に赤いエラーがないか確認できます。

確認の順番:ファイルを保存したか → ブラウザを再読み込みしたか → idが一致するか → Consoleにエラーがないか、の順で見ると原因を絞りやすくなります。

タイマーが1秒ずつ減る仕組み

JavaScriptのsetInterval()は、決めた間隔で処理を繰り返します。今回の1000は1000ミリ秒、つまり1秒です。

1秒ごとに残り時間を減らす
timerId = setInterval(() => {
  remaining--;
  draw();
}, 1000);

3分は180秒です。Math.floor(remaining / 60)で「分」を、remaining % 60で「秒」を計算します。179秒なら2分59秒なので、画面には「02:59」と表示されます。

各時間ボタンのdata-secondsへ秒数を入れておけば、同じJavaScriptで複数の時間を扱えます。7分を追加する時は420秒です。

HTMLファイルとWeb公開は別の作業

自分のパソコンで動いたHTMLは、まだほかの人がURLから開ける状態ではありません。

Web上で使えるようにするには、HTMLファイルをWebサーバーへ配置します。静的なラーメンタイマーなら、レンタルサーバー、GitHub Pages、Cloudflare Pages、Netlify、Vercelなどで公開できます。

公開時の基本構成
ramen-timer/
└── index.html

多くのWebサーバーは、フォルダのURLへアクセスすると中のindex.htmlを自動で表示します。そのため、公開用はramen-timer/index.htmlという構成が便利です。

今回の公開URL:https://techbeginnerguide.jp/tools/ramen-timer/ から、実際に動く完成版を利用できます。

スマートフォン対応で確認すること

  • viewport:端末の画面幅に合わせるため、head内へviewportのmetaタグを入れる
  • ボタンの大きさ:指で押しやすい高さと余白を確保する
  • 横はみ出し:長いコードや画像だけが画面の外へ飛び出さないようにする
  • 背景復帰:画面を閉じた間も正確に測るなら、終了予定時刻との差で残り時間を計算する
  • 音と振動:端末やブラウザによって対応が異なるため、表示でも終了を伝える

CSSのclamp()を使うと、大きな残り時間を画面幅に合わせて縮められます。ボタンにはtouch-action: manipulationを指定すると、タップ操作を意識した実装になります。

次に追加できる機能

  • 1分から10分までの自由入力
  • 終了音の種類と音量選択
  • カップ麺の商品別プリセット
  • 醤油・味噌・豚骨のテーマ切り替え
  • 複数タイマーの同時実行
  • PWA化とホーム画面への追加
  • QRコードからの起動

一度に全部を追加せず、「1機能を足す → ブラウザで確認する → 問題があれば戻す」という小さな単位で進めるのが安全です。

AIを使って作る時も、最後は実機確認が必要

AIへ「3分・4分・5分を選べる、スマホ対応のラーメンタイマーをHTML・CSS・JavaScriptで作って」と頼めば、コードのたたき台を作れます。

ただし、AIがコードを出したことと、そのコードが実際の環境で動くことは別です。次の順番で確認しましょう。

  1. AIへ作りたい機能と見た目を具体的に伝える
  2. 生成されたコードをHTMLファイルへ保存する
  3. パソコンとスマートフォン幅で表示する
  4. すべての時間ボタンと操作ボタンを押す
  5. エラーを直し、もう一度同じ操作を確認する
  6. Webサーバーへ公開し、実際のURLで再確認する
大切なのは「AIに作らせる力+動作を確かめる力」です。小さなタイマーでも、画面作り、動き、デバッグ、Web公開という開発の基本を一通り体験できます。

よくある質問

ラーメンタイマーはアプリのインストールが必要ですか?

必要ありません。HTML・CSS・JavaScriptだけで作られたページなので、ChromeやSafariなどのWebブラウザで利用できます。

HTMLファイルを作ればインターネットで公開されますか?

いいえ。パソコン内のHTMLファイルは自分の端末で開けますが、ほかの人がURLから使うにはWebサーバーへ配置する必要があります。

画面は表示されるのにボタンが動かない原因は何ですか?

JavaScriptの読み込み位置、HTMLとJavaScriptのidの不一致、記号の入力ミスなどを確認します。ブラウザの開発者ツールに表示されるエラーも手掛かりになります。

スマートフォンでも使えますか?

viewport設定と押しやすいボタンサイズを用意すれば使えます。公開版は画面を閉じた時間も時刻差で補正し、対応端末では終了時に音と振動で知らせます。

まとめ

  • HTMLで画面、CSSで見た目、JavaScriptでタイマーの動きを作る
  • 最初は1つのHTMLファイルにまとめると試しやすい
  • 表示されても、すべてのボタンが動くとは限らない
  • id、JavaScriptの位置、記号、Consoleのエラーを確認する
  • ローカルで動くことと、URLから使えるWeb公開は別
  • スマホ幅、押しやすさ、横はみ出し、音が出ない場合も確認する

ラーメンが完成する数分を測るだけの小さなツールでも、立派なWebアプリです。完成版を触ってからコードへ戻ると、それぞれの行が何をしているのか理解しやすくなります。

🍜 完成版ラーメンタイマーを開く

関連記事