3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

個人的に好きなCSSアニメーション

Posted at

「オシャレなWebページ○○選」「Webデザイントレンド2025」のようなまとめを見ていて、「このエフェクト、かっこいいな」と思うことがよくあります。

好きなCSSアニメーションは無数にありますが、今回は、個人的に特に気に入っているものを4つ紹介します。どれもJavaScriptなしで実装でき、滑らかで美しいアニメーションばかり!

実装コードも掲載しているので、気に入ったものがあればぜひ使用してみてください!

1. スクロールを促す矢印アニメーション

ページの下部にコンテンツがあることを示す、シンプルだけど効果的なアニメーションです。矢印がスーッと滑らかに動き、ユーザーの視線を自然と誘導します。

See the Pen Untitled by STELLAR INTER (@STELLAR-INTER) on CodePen.

実装コード

<!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 {
      margin: 0;
      min-height: 200vh;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      display: flex;
      justify-content: center;
      align-items: center;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    }

    .scroll-indicator {
      position: fixed;
      bottom: 40px;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 20px;
    }

    .scroll-text {
      color: rgba(255, 255, 255, 0.9);
      font-size: 14px;
      font-weight: 500;
      letter-spacing: 2px;
      text-transform: uppercase;
      opacity: 0;
      animation: fadeIn 0.8s ease-out 0.5s forwards;
    }

    @keyframes fadeIn {
      to {
        opacity: 1;
      }
    }

    .arrow-container {
      position: relative;
      width: 30px;
      height: 50px;
    }

    .arrow {
      position: absolute;
      left: 50%;
      transform: translateX(-50%);
      width: 2px;
      height: 30px;
      background: linear-gradient(
        to bottom,
        rgba(255, 255, 255, 0),
        rgba(255, 255, 255, 0.8)
      );
      animation: scrollDown 1.5s ease-in-out infinite;
    }

    .arrow::before,
    .arrow::after {
      content: '';
      position: absolute;
      bottom: 0;
      width: 8px;
      height: 1px;
      background: rgba(255, 255, 255, 0.8);
    }

    .arrow::before {
      left: -7px;
      transform: rotate(45deg);
      transform-origin: right center;
    }

    .arrow::after {
      right: -7px;
      transform: rotate(-45deg);
      transform-origin: left center;
    }

    @keyframes scrollDown {
      0% {
        transform: translateX(-50%) translateY(-05px);
        opacity: 0;
      }
      50% {
        opacity: 1;
      }
      100% {
        transform: translateX(-50%) translateY(10px);
        opacity: 0;
      }
    }

    /* コンテンツエリア */
    .content {
      position: absolute;
      top: 30%;
      color: white;
      text-align: center;
    }

    .content h1 {
      font-size: 48px;
      margin: 0 0 20px 0;
      font-weight: 700;
    }

    .content p {
      font-size: 18px;
      opacity: 0.9;
    }
  </style>
</head>
<body>
  <div class="content">
    <h1>Welcome</h1>
    <p>スクロールして詳細を見る</p>
  </div>

  <div class="scroll-indicator">
    <span class="scroll-text">Scroll</span>
    <div class="arrow-container">
      <div class="arrow"></div>
    </div>
  </div>
</body>
</html>

ポイント

  • 3本の矢印を時間差で表示することで、流れるような動きを実現
  • transform: translateY()で滑らかな移動感を演出
  • グラデーションを使って矢印の先端が徐々に現れる効果を追加
  • 疑似要素で矢印の先端部分を作成し、DOMをシンプルに保つ

使いどころ

  • ランディングページのファーストビュー
  • 長いコンテンツの導入部分
  • モバイルサイトのナビゲーション補助

あとは、ただの棒だけを表示するっていうのもなかなかシンプルで洗練されていて好きですね。

See the Pen Untitled by STELLAR INTER (@STELLAR-INTER) on CodePen.

<!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 {
      margin: 0;
      min-height: 200vh;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      display: flex;
      justify-content: center;
      align-items: center;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    }

    .scroll-indicator {
      position: fixed;
      bottom: 40px;
      display: flex;
      flex-direction: column;
      align-items: center;
      gap: 20px;
    }

    .scroll-text {
      color: rgba(255, 255, 255, 0.9);
      font-size: 14px;
      font-weight: 500;
      letter-spacing: 2px;
      text-transform: uppercase;
      opacity: 0;
      animation: fadeIn 0.8s ease-out 0.5s forwards;
    }

    @keyframes fadeIn {
      to {
        opacity: 1;
      }
    }

    .arrow-container {
      position: relative;
      width: 30px;
      height: 50px;
      display:flex;
      justify-content:center;
    }
    .arrow-container-inner{
      position:relative;
      width:2px;
      height:40px;
      overflow:hidden;
    }

    .arrow {
      position: absolute;
      left: 50%;
      transform: translateX(-50%);
      width: 2px;
      height: 50px;
      background: rgba(255,255,255,0.6);
      animation: scrollDown 2.5s ease-in-out infinite;
    }

    @keyframes scrollDown {
      0% {
        transform: translateX(-50%) translateY(-110%);
        opacity: 1;
      }
      50% {
        opacity: 1;
      }
      100% {
        transform: translateX(-50%) translateY(150%);
        opacity: 0;
      }
    }

    /* コンテンツエリア */
    .content {
      position: absolute;
      top: 30%;
      color: white;
      text-align: center;
    }

    .content h1 {
      font-size: 48px;
      margin: 0 0 20px 0;
      font-weight: 700;
    }

    .content p {
      font-size: 18px;
      opacity: 0.9;
    }
  </style>
</head>
<body>
  <div class="content">
    <h1>Welcome</h1>
    <p>スクロールして詳細を見る</p>
  </div>

  <div class="scroll-indicator">
    <span class="scroll-text">Scroll</span>
    <div class="arrow-container">
      <dic class="arrow-container-inner">
      <div class="arrow"></div>
      </div>
    </div>
  </div>
</body>
</html>

2. ホバーで展開する3Dピラミッド

かなり昔に遊び用で作ったCSSアニメーションです。この記事は「JavaScriptなし」と謳っておきながら、このアニメーションだけはクリックイベント取得用でJSが入っています。

See the Pen Untitled by STELLAR INTER (@STELLAR-INTER) on CodePen.

実装コード

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>3D-Pyramid</title>
    <link rel="stylesheet" href="style.css">
    <style>
        * {
            margin: 0px;
            padding: 0px;
            box-sizing: border-box;
        }

        body {
            position: relative;
            display: flex;
            justify-content: center;
            align-items: center;
            width: 100%;
            min-height: 100vh;
            background: #050505;
        }

        .pyramid {
            position: absolute;
            width: 200px;
            height: 200px;
            transform-style: preserve-3d;
            transition: 2s;
            animation: animate 10s linear infinite;
        }

        @keyframes animate {
            0% {
                transform: rotateX(-20deg) rotateY(0deg);
            }

            100% {
                transform: rotateX(-20deg) rotateY(360deg);
            }
        }

        .pyramid div {
            position: absolute;
            top: 0px;
            left: 0px;
            width: 100%;
            height: 100%;
            transform-style: preserve-3d;
        }

        .pyramid .bottom {
            position: absolute;
            top: 0px;
            left: 0px;
            width: 100%;
            height: 100%;
            background: repeating-radial-gradient(#d7dadc, #fff);
            transform: rotateX(90deg) translateZ(-100px);
            transition: 1.5s;
        }

        .pyramid .bottom.open {
            transform: rotateX(90deg) translateZ(-121px);
        }

        .pyramid .p-span {
            position: absolute;
            top: 0px;
            left: 0px;
            width: 100%;
            height: 100%;
            background: linear-gradient(#55595d, #ffffff);
            clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
            animation: animatepyramid-def 1.5s forwards;
            /*transform: rotateY(calc(90deg * var(--i))) translateZ(99px) rotateX(30deg)translateY(0px);*/
            transform-origin: bottom;
            transition: 1s;
        }

        @keyframes animatepyramid-def {
            0% {

                transform: rotateY(calc(90deg * var(--i))) translateZ(145px) rotateX(-65deg) translateY(50px);
            }

            100% {
                transform: rotateY(calc(90deg * var(--i))) translateZ(99px) rotateX(30deg);
            }
        }

        .pyramid .p-span.open {
            transition: 1s;
            animation: animatepyramid 2s forwards;
        }

        @keyframes animatepyramid {
            0% {
                transform: rotateY(calc(90deg * var(--i))) translateZ(99px) rotateX(30deg);
            }

            50% {
                transform: rotateY(calc(90deg * var(--i))) translateZ(245px) rotateX(-65deg) translateY(100px);
            }

            100% {
                transform: rotateY(calc(90deg * var(--i))) translateZ(145px) rotateX(-65deg) translateY(50px);
            }
        }

        .glow {
            position: absolute;
            top: 0px;
            left: 0px;
            width: 100%;
            height: 100%;
            background: #fff;
            transform: rotateX(90deg) translateZ(-200px);
            filter: blur(20px);
            box-shadow: 0 0 120px #fff;
        }

        .click-box {
            position: absolute;
            top: 50px;
            width: 150px;
            height: auto;
            padding: 20px;
            line-height: 0;
            box-shadow: 0 0 5px #fff, 0 0 10px #fff, inset 0 0 5px #fff, inset 0 0 10px #fff;
            border-radius: 50px;
            border: 1px solid #fff;
            text-align: center;
            letter-spacing: 5px;
            color: #fff;
            font-weight: 100;
            text-shadow: 0 0 1px #fff, 0 0 2px #fff, 0 0 5px #fff, 0 0 5px #fff, 0 0 5px #fff, 0 0 10px #fff, 0 0 10px #fff;
        }

        .click-box:hover {
            cursor: pointer;
        }


        .cube-box div,
        .cube-box span {
            width: 50px;
            height: 50px;
            position: absolute;
            left: 37%;
            top: 100px;
            transform-style: preserve-3d;
        }

        .cube-box {
            position: relative;
            display: flex;
            justify-content: center;
            align-items: center;
        }

        .cube {
            position: relative;
            transform-style: preserve-3d;
            animation: animatecube 4s linear infinite;
            transition: 1.5s;
        }

        @keyframes animatecube {
            0% {
                transform: rotateY(360deg);
            }

            100% {
                transform: rotateY(0deg);
            }
        }

        .cube .cube-in {
            position: absolute;
            top: 0px;
            left: 0px;
            width: 100%;
            height: 100%;
            transform-style: preserve-3d;
            transition: 1.5s;
            opacity: 1;
        }

        .cube .c-span {
            transform-style: preserve-3d;
            position: absolute;
            top: 0px;
            left: 0px;
            width: 100%;
            height: 100%;
            background: repeating-radial-gradient(#e0ffff, #3cb371);
            transform: rotateY(calc(90deg * var(--i)))translateZ(25px);
            opacity: 1;
            display: inline-block;
            transition: 1.5s;
        }

        .cube-top {
            transition: 1.5s;
            width: 50px;
            height: 50px;
            transform-style: preserve-3d;
            position: absolute;
            top: 0;
            left: 0;
            background: repeating-radial-gradient(#e0ffff, #3cb371);
            transform: rotateX(90deg)translateZ(25px);
        }
    </style>
</head>

<body>
    <div class="click-box">
        CLICK
    </div>
    <div class="pyramid">
        <div class="glow"></div>
        <div class="glow-pyramid"></div>
        <div class="glow-pyramid"></div>
        <div class="glow-pyramid"></div>
        <div class="glow-pyramid"></div>
        <div>
            <span class="p-span" style="--i:0;"></span>
            <span class="p-span" style="--i:1;"></span>
            <span class="p-span" style="--i:2;"></span>
            <span class="p-span" style="--i:3;"></span>
            <span class="bottom"></span>


            <div class="cube-box">
                <div class="cube">
                    <ul class="cube-top"></ul>
                    <div class="cube-in">
                        <span class="c-span click" style="--i:0"></span>
                        <span class="c-span click" style="--i:1"></span>
                        <span class="c-span click" style="--i:2"></span>
                        <span class="c-span click" style="--i:3"></span>
                    </div>
                    <ul class="cube-bottom-shadow"></ul>
                </div>
            </div>


        </div>
    </div>
    <script>
        const clickBox = document.querySelector('.click-box');
        const spans = document.querySelectorAll('.p-span');
        const bottom = document.querySelector('.bottom');

        clickBox.addEventListener('click', function () {
            spans.forEach(function (span) {
                span.classList.toggle('open');
            });
            bottom.classList.toggle('open');
        });
    </script>
</body>
</html>

ポイント

  • CSSだけで3Dピラミッドを構築している
    transform-style: preserve-3dとrotateX・rotateYの組み合わせで、擬似的な立体ピラミッドを作っています。各面(.p-span)にはclip-pathで三角形の形状を与えてるのがミソ。
  • ピラミッド内部に3Dキューブを配置
    .cube-box以下に立方体を定義しており、rotateYのアニメーションでくるくる回転するキューブが内部で動く。ピラミッドが開くと中のキューブが見える仕掛けになっています。

使いどころ

  • ありません。ただ個人的にこういうのを作るのが好きなだけです。

3. ガラスモーフィズムカード

みんな大好きガラスモーフィズムエフェクト。背景が透けて見える美しい表現です。

See the Pen Untitled by STELLAR INTER (@STELLAR-INTER) on CodePen.

実装コード

<!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 {
      margin: 0;
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
      background: linear-gradient(135deg, #e8f5e9 0%, #c8e6c9 50%, #a5d6a7 100%);
      position: relative;
      overflow: hidden;
    }

    body::before,
    body::after {
      content: '';
      position: absolute;
      width: 500px;
      height: 500px;
      border-radius: 50%;
      filter: blur(100px);
      opacity: 0.4;
      animation: float 20s ease-in-out infinite;
    }

    body::before {
      background: linear-gradient(135deg, #66bb6a 0%, #43a047 100%);
      top: -200px;
      left: -200px;
    }

    body::after {
      background: linear-gradient(135deg, #81c784 0%, #66bb6a 100%);
      bottom: -200px;
      right: -200px;
      animation-delay: -10s;
    }

    @keyframes float {
      0%, 100% { transform: translate(0, 0) scale(1); }
      33% { transform: translate(100px, -50px) scale(1.1); }
      66% { transform: translate(-50px, 100px) scale(0.9); }
    }

    .glass-container {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
      gap: 30px;
      padding: 40px;
      max-width: 1200px;
      z-index: 1;
    }

    .glass-card {
      position: relative;
      padding: 40px;
      background: rgba(255, 255, 255, 0.6);
      backdrop-filter: blur(20px) saturate(180%);
      border-radius: 20px;
      border: 1px solid rgba(255, 255, 255, 0.8);
      box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1), inset 0 1px 0 rgba(255, 255, 255, 0.9);
      transition: transform 0.3s ease, box-shadow 0.3s ease;
      overflow: hidden;
    }

    .glass-card::before {
      content: '';
      position: absolute;
      top: 0;
      left: -100%;
      width: 100%;
      height: 100%;
      background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.5), transparent);
      transition: left 0.5s ease;
    }

    .glass-card:hover::before { left: 100%; }

    .glass-card:hover {
      transform: translateY(-5px);
      box-shadow: 0 12px 48px rgba(0, 0, 0, 0.15), inset 0 1px 0 rgba(255, 255, 255, 1);
    }

    .card-icon {
      width: 60px;
      height: 60px;
      border-radius: 15px;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 30px;
      margin-bottom: 20px;
    }

    .icon1 { background: linear-gradient(135deg, #66bb6a 0%, #43a047 100%); box-shadow: 0 8px 16px rgba(102, 187, 106, 0.4); }
    .icon2 { background: linear-gradient(135deg, #81c784 0%, #66bb6a 100%); box-shadow: 0 8px 16px rgba(129, 199, 132, 0.4); }
    .icon3 { background: linear-gradient(135deg, #4caf50 0%, #388e3c 100%); box-shadow: 0 8px 16px rgba(76, 175, 80, 0.4); }

    h2 {
      margin: 0 0 15px 0;
      font-size: 24px;
      font-weight: 700;
      color: #2e7d32;
      letter-spacing: -0.5px;
    }

    p {
      margin: 0 0 20px 0;
      font-size: 15px;
      color: #558b2f;
      line-height: 1.6;
    }

    .glass-button {
      padding: 12px 24px;
      background: rgba(255, 255, 255, 0.5);
      backdrop-filter: blur(10px);
      border: 1px solid rgba(102, 187, 106, 0.3);
      border-radius: 10px;
      color: #2e7d32;
      font-size: 14px;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.3s ease;
      display: inline-block;
    }

    .glass-button:hover {
      background: rgba(255, 255, 255, 0.8);
      border-color: rgba(102, 187, 106, 0.5);
      transform: translateY(-2px);
      box-shadow: 0 4px 12px rgba(102, 187, 106, 0.3);
    }
  </style>
</head>
<body>
  <div class="glass-container">
    <div class="glass-card">
      <div class="card-icon icon1"></div>
      <h2>AAAAA</h2>
      <p>ここにテキストを書いたりします</p>
      <button class="glass-button">詳細を見る</button>
    </div>

    <div class="glass-card">
      <div class="card-icon icon2"></div>
      <h2>BBBBB</h2>
      <p>ここにテキストを書いたりします</p>
      <button class="glass-button">詳細を見る</button>
    </div>

    <div class="glass-card">
      <div class="card-icon icon3"></div>
      <h2>CCCCC</h2>
      <p>ここにテキストを書いたりします</p>
      <button class="glass-button">詳細を見る</button>
    </div>
  </div>
</body>
</html>

ポイント

  • backdrop-filter: blur(20px)で背景をぼかす (すりガラス風)
  • 疑似要素でホバー時の光沢効果を追加

ブラウザ対応

2025年時点でbackdrop-filterは主要ブラウザで97%以上サポートされています。古いブラウザ向けには、フォールバックとして不透明な背景色を設定しておくと安全です。

@supports not (backdrop-filter: blur(20px)) {
  .glass-card {
    background: rgba(30, 30, 50, 0.8);
  }
}

使いどころ

  • モーダルウィンドウ
  • ナビゲーションバー
  • プライシングカード
  • ダッシュボードのウィジェット

4. ネオンライトテキスト

80年代風のネオンサインを再現したテキストエフェクトです。複数のtext-shadowを重ねることで、リアルな発光感を表現します。

See the Pen Untitled by STELLAR INTER (@STELLAR-INTER) on CodePen.

実装コード

<!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 {
      margin: 0;
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      background: #0a0a0a;
      font-family: 'Roboto', sans-serif;
      overflow: hidden;
    }

    .neon-container {
      text-align: center;
    }

    .neon-text {
      font-size: 80px;
      font-weight: 100;
      letter-spacing: 8px;
      margin: 0;
      text-transform: uppercase;
      animation: neonGlow 3s ease-in-out infinite alternate;
    }

    @keyframes neonGlow {
      0% {
        color: #fff;
        text-shadow: 
          0 0 2px #fff,
          0 0 5px #fff,
          0 0 10px #fff,
          0 0 20px #fff,
          0 0 30px #ff006e,
          0 0 40px #ff006e,
          0 0 50px #ff006e,
          0 0 60px #ff006e,
          0 0 70px #ff006e;
      }
      25% {
        color: #fff;
        text-shadow: 
          0 0 2px #fff,
          0 0 5px #fff,
          0 0 10px #fff,
          0 0 20px #fff,
          0 0 30px #00f5ff,
          0 0 40px #00f5ff,
          0 0 50px #00f5ff,
          0 0 60px #00f5ff,
          0 0 70px #00f5ff;
      }
      50% {
        color: #fff;
        text-shadow: 
          0 0 2px #fff,
          0 0 5px #fff,
          0 0 10px #fff,
          0 0 20px #fff,
          0 0 30px #7fff00,
          0 0 40px #7fff00,
          0 0 50px #7fff00,
          0 0 60px #7fff00,
          0 0 70px #7fff00;
      }
      75% {
        color: #fff;
        text-shadow: 
          0 0 2px #fff,
          0 0 5px #fff,
          0 0 10px #fff,
          0 0 20px #fff,
          0 0 30px #ffd500,
          0 0 40px #ffd500,
          0 0 50px #ffd500,
          0 0 60px #ffd500,
          0 0 70px #ffd500;
      }
      100% {
        color: #fff;
        text-shadow: 
          0 0 2px #fff,
          0 0 5px #fff,
          0 0 10px #fff,
          0 0 20px #fff,
          0 0 30px #ff00ff,
          0 0 40px #ff00ff,
          0 0 50px #ff00ff,
          0 0 60px #ff00ff,
          0 0 70px #ff00ff;
      }
    }

  </style>
</head>
<body>
  <div class="neon-container">
    <h1 class="neon-text">NEON LIGHTS</h1>
  </div>
</body>
</html>

使いどころ

  • ローディング画面やイントロページのタイトル演出
  • 「Coming Soon」「Now Loading」「Cyberpunk」系のサイトテーマ
  • ゲーム・音楽・イベント系Webサイトのヘッダーやタイトルロゴ
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?