CSSとJavaScriptでふわっと湯気を再現してみた

作ってみたシリーズ

先日、街のカフェでホットコーヒーを飲んでいたとき、「この湯気ってコードで再現できないかな?」と思ったのがきっかけで、CSSとJavaScriptだけで湯気アニメーションを作ってみました。

アニメーションって敷居が高そうに感じるかもしれませんが、今回はHTML/CSS/JavaScriptだけで実装できるので、初心者の方にもおすすめです。

以下が実際のデモです(コピペでそのまま動きます):

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>湯気アニメーション</title>
  <style>
    body {
      background: #40342a;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      margin: 0;
    }

    .cup {
      width: 120px;
      height: 140px;
      background: #8b5e3c;
      border-radius: 0 0 60px 60px;
      position: relative;
      overflow: visible;
      box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
    }

    .steam-container {
      position: absolute;
      top: -30px;
      left: 0;
      width: 100%;
      height: 150px;
      pointer-events: none;
      overflow: visible;
      z-index: 1;
    }

    .steam {
      position: absolute;
      bottom: 100px;
      width: 20px;
      height: 20px;
      background: rgba(255, 255, 255, 0.6);
      border-radius: 50%;
      filter: blur(4px);
      animation: floatUp 4s ease-out forwards;
      opacity: 0;
      z-index: 2;
    }

    @keyframes floatUp {
      0% {
        transform: translate(0, 0) scale(1);
        opacity: 0.6;
      }
      25% {
        transform: translate(-15px, -30px) scale(1.2);
        opacity: 0.7;
      }
      50% {
        transform: translate(15px, -60px) scale(1.5);
        opacity: 0.5;
      }
      75% {
        transform: translate(-10px, -90px) scale(1.7);
        opacity: 0.4;
      }
      100% {
        transform: translate(0, -130px) scale(2);
        opacity: 0;
      }
    }
  </style>
</head>
<body>
  <div class="cup">
    <div class="steam-container"></div>
  </div>

  <script>
    const container = document.querySelector('.steam-container');

    function createSteam() {
      const steam = document.createElement('div');
      steam.classList.add('steam');

      const size = Math.random() * 10 + 20;
      steam.style.width = `${size}px`;
      steam.style.height = `${size}px`;
      steam.style.left = `${Math.random() * 80 + 10}px`;
      steam.style.filter = `blur(${Math.random() * 3 + 2}px)`;

      container.appendChild(steam);

      setTimeout(() => {
        steam.remove();
      }, 4000);
    }

    setInterval(() => {
      createSteam();
      if (Math.random() > 0.3) createSteam();
    }, 500);
  </script>
</body>
</html>
湯気アニメーション

3.1.湯気の見た目は CSS で再現

.steam {
  background: rgba(255, 255, 255, 0.6);
  border-radius: 50%;
  filter: blur(4px);
  ...
}

ここでは .steam というクラスで1つの湯気を表現しています。ぼかし効果filter: blur())を加えることで、煙のように柔らかく見える白い丸を作り、それを border-radius: 50%完全な円形にしています。

さらに background: rgba() を使うことで、透明度を調整し、「空気に溶け込むような」質感を出しています。

3.2.湯気の動きは @keyframes で実現

@keyframes floatUp {
  0%   { transform: translate(0, 0) scale(1);   opacity: 0.6; }
  25%  { transform: translate(-15px, -30px) scale(1.2); opacity: 0.7; }
  50%  { transform: translate(15px, -60px) scale(1.5);  opacity: 0.5; }
  75%  { transform: translate(-10px, -90px) scale(1.7); opacity: 0.4; }
  100% { transform: translate(0, -130px) scale(2);      opacity: 0; }
}

このアニメーションでは、湯気がふわふわと左右に揺れながら上昇する動きを作っています。

  • translate(X, Y):左右に揺れるようにx軸を変えながら、y軸で上昇。
  • scale():上に行くほど大きく見えるように拡大。
  • opacity:消えていくように透明に。

この3つを組み合わせることで、自然で柔らかい湯気の動きを実現しています。

3.3.JavaScriptで湯気をランダムに生成

function createSteam() {
  const steam = document.createElement('div');
  steam.classList.add('steam');

  const size = Math.random() * 10 + 20;
  steam.style.width = `${size}px`;
  steam.style.height = `${size}px`;
  steam.style.left = `${Math.random() * 80 + 10}px`;
  steam.style.filter = `blur(${Math.random() * 3 + 2}px)`;

  container.appendChild(steam);

  setTimeout(() => steam.remove(), 4000);
}

この関数は、新しい湯気の要素を1つ作って .steam-container に追加し、4秒後に削除しています。

ポイントは:

  • Math.random() を使って、湯気のサイズ・位置・ぼかし度合いを毎回変えていること。
  • これによって、すべての湯気が少しずつ違う見た目になり、リアルさが増しています。
  • 湯気は setInterval() で一定間隔ごとに生成されているので、止まらずふわふわ出続けます。
setInterval(() => {
  createSteam();
  if (Math.random() > 0.3) createSteam(); // ランダムで2つ出ることも
}, 500);

このランダム性が、「自然に見えるアニメーション」を作る上でとても重要です。

「湯気」という抽象的なものでも、CSSとJavaScriptだけでここまで再現できるのが面白かったです。
今回のポイントは:

  • CSSの bluropacity を活かすことでリアルな質感を演出
  • @keyframes で自然な動きを作る
  • JavaScriptでランダム生成して、単調にならないようにする

ちょっとした遊び心で始めたコードが、想像以上に面白いものになりました。

コメント

タイトルとURLをコピーしました