【Service Card Section】ふわっと表示する1カラム用のサービス紹介カードを実装する方法

この記事では、サービス紹介カードをふわっと表示させるアニメーション(Service Card Section)を実装する方法を紹介します。
LPなどの1カラムの固定ページに最適です。

1 実装のポイント

  • スクロール時にカードが下からふわっと表示されます。
  • IntersectionObserver を利用して軽量で高パフォーマンス。
  • 1カラムの固定ページで読み込むように制御しています。

2 functions.php にコードを追加

注意: 必ず子テーマの functions.php に追加してください。親テーマに直接追加するとアップデートで消える可能性があります。


// ----------------------------------------------------
// カードをふわっと表示するアニメーションを追加
// ----------------------------------------------------
add_action('wp_footer', function() {
  if (!(is_single() || is_page())) return; // 投稿または固定ページのみ
    ?>
    <script>
    document.addEventListener('DOMContentLoaded', function() {
      const cards = document.querySelectorAll('.card_item figure.card_item_block');
      if (!cards.length) return;

      // 初期状態:非表示解除(JS効かない場合に備えフェールセーフ)
      cards.forEach(el => el.style.opacity = '0');

      // IntersectionObserver が使える場合のみ
      if ('IntersectionObserver' in window) {
        const observer = new IntersectionObserver((entries, obs) => {
          entries.forEach(entry => {
            if (entry.isIntersecting) {
              entry.target.classList.add('is-visible');
              obs.unobserve(entry.target);
            }
          });
        }, { threshold: 0.1 });
        cards.forEach(card => observer.observe(card));
      } else {
        // 古いブラウザの場合は即表示
        cards.forEach(el => el.classList.add('is-visible'));
      }
    });
    </script>
    <?php
});

3 Javascriptにコードを追加

ファイル名:fadein-cards.js
保存先:wp-content/themes/child-theme/js/fadein-cards.js


//-------------------------------------------
// カードをふわっと表示するアニメーションを追加
//-------------------------------------------
document.addEventListener('DOMContentLoaded', function() {
  const items = document.querySelectorAll('.card_item figure.card_item_block');

  if (!('IntersectionObserver' in window)) {
    // 対応してない古いブラウザ用:すぐ表示
    items.forEach(el => el.classList.add('is-visible'));
    return;
  }

  const observer = new IntersectionObserver((entries, obs) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        entry.target.classList.add('is-visible');
        obs.unobserve(entry.target);
      }
    });
  }, {
    root: null,
    rootMargin: '0px 0px -10% 0px', // 少し早めに発火
    threshold: 0.1
  });

  items.forEach(el => observer.observe(el));
});

3.1 ディレクトリ構造

  • child-theme/
    • archive.php
    • category.php
    • functions.php
    • footer.php
    • header.php
    • style.css
    • js/
      • fadein-cards.js

4 HTML構造(カード部分)


<div class="card_item">
  <figure class="card_item_block">
    <div class="fadein-service-card card-one">
      <img src="https://wordpress-tips.net/wp-content/uploads/2025/10/003.jpg" alt="猫">
      <h3>猫</h3>
      <ul>
        <li>気まぐれだけど、実は甘えん坊</li>
        <li>マイペースで静かな時間が好き</li>
        <li>お気に入りの場所で日向ぼっこ</li>
      </ul>
      <a href="https://wordpress-tips.net/" class="more-link">詳しく見る</a>
    </div>
  </figure>

  <figure class="card_item_block">
    <div class="fadein-service-card card-two">
      <img src="https://wordpress-tips.net/wp-content/uploads/2025/10/005.jpg" alt="コアラ">
      <h3>コアラ</h3>
      <ul>
        <li>おっとりマイペースで穏やか</li>
        <li>木の上が大好きなリラックス派</li>
        <li>睡眠時間は1日18時間以上!</li>
      </ul>
      <a href="https://wordpress-tips.net/" class="more-link">詳しく見る</a>
    </div>
  </figure>

  <figure class="card_item_block">
    <div class="fadein-service-card card-three">
      <img src="https://wordpress-tips.net/wp-content/uploads/2025/10/002.jpg" alt="犬">
      <h3>犬</h3>
      <ul>
        <li>忠実で仲間思いな性格</li>
        <li>遊ぶことと人が大好き!</li>
        <li>元気いっぱいで毎日がアクティブ</li>
      </ul>
      <a href="https://wordpress-tips.net/" class="more-link">詳しく見る</a>
    </div>
  </figure>
</div>

5 汎用CSS


/* -----------------------------------------
 * カードをふわっと表示するアニメーションを追加
 * -------------------------------------- */

/* カード全体を包むコンテナ */
.card_item {
  max-width: 1200x; /* ← 横幅制限 LPだと1080px~1200px 自由に変えてください */
  margin:0 auto;
  padding: 20px; /** 内側余白 **/
  display: flex; /** 横並び配置 **/
  flex-wrap: wrap; /** 折り返しを許可 **/
  justify-content: center; /** 中央寄せ **/
  align-items: flex-start; /** 上揃え **/
  gap: 30px; /** ★ 横間隔を30pxに調整 **/
  background: #fff; /** 背景色を白に **/
  box-sizing: border-box; /** ボックス計算をborder込みに **/
}

/* カード(figure) */
.card_item figure.card_item_block {
  margin: 0; /** 外側余白リセット **/
  padding: 0; /** 内側余白リセット **/
  float: none !important; /** float解除 **/
  display: flex; /** フレックス表示 **/
  justify-content: center; /** 中央寄せ **/
  box-sizing: border-box; /** 幅計算をborder込みに **/
  width: calc((100% - 60px) / 3); /** gap(30×2)を除いた3等分幅 **/
  min-width: 260px; /** 最小幅指定で崩れ防止 **/
}

/* スマホ(~960px):1列表示 */
@media screen and (max-width: 960px) {
  .card_item {
    justify-content: center; /** 中央寄せ **/
    gap: 25px; /** スマホ時の隙間調整 **/
  }
  .card_item figure.card_item_block {
    width: 90%; /** 幅を広げて1列表示 **/
  }
}

/* 中のカード */
.fadein-service-card {
	width: 100%; /** カード幅100% **/
	background: #fff; /** 背景白 **/
	border-radius: 10px; /** 角丸 **/
	box-shadow: 0 4px 10px rgba(0,0,0,0.1); /** 軽い影 **/
	padding: 15px; /** 内側余白 **/
	box-sizing: border-box; /** 枠込み計算 **/
	transition: transform 0.3s ease; /** ホバー時アニメーション **/
}
.fadein-service-card:hover {
	transform: translateY(-5px); /** ホバーで少し浮く **/
}

/* オーバーレイ(半透明レイヤー) */
.fadein-service-card::after {
  position: relative; /* この要素を基準にして、子要素(position:absolute)や ::after の位置を決めるための基準点を作る */
  content: ""; /** 擬似要素生成 **/
  position: absolute; /** カード全体に重ねる **/
  inset: 0; /** 全方向0指定 **/
  background: rgba(173, 216, 230, 0); /** 初期は透明 **/
  transition: background 0.3s ease; /** 色変化を滑らかに **/
  border-radius: 12px; /** 角丸を維持 **/
  z-index: 2; /** 画像の上・テキストの下に配置 **/
  pointer-events: none; /** クリック無効化 **/
}

/* ホバー時に水色オーバーレイを表示 */
.fadein-service-card {
  transition: background 0.3s ease; /** 背景変更アニメーション **/
}
.fadein-service-card:hover {
  background: #eeffff; /** 水色に変化 **/
}

/* 画像をレスポンシブ対応 */
.fadein-service-card img {
	width: 100%; /** 横幅いっぱい **/
	height: auto; /** 縦横比を維持 **/
	border-radius: 5px; /** 画像角を丸める **/
}

/* テキスト類を画像より上に表示 */
.fadein-service-card h3,
.fadein-service-card ul,
.fadein-service-card a {
  position: relative; /** テキスト層を独立化 **/
  z-index: 3; /** 画像上に配置 **/
}

/* リスト(黒丸非表示) */
.fadein-service-card ul {
  list-style: none; /** 黒丸削除 **/
  padding: 0; /** 内側余白削除 **/
  margin: 0; /** 外側余白削除 **/
}
.fadein-service-card ul li {
  font-size: 0.9rem; /** 小さめ文字 **/
  color: #333; /** 文字色 **/
  line-height: 1.6; /** 行間広め **/
  margin-bottom: 5px; /** 下余白 **/
}

/* 下からふわっと */
.card_item figure.card_item_block {
  opacity: 0; /** 初期は透明 **/
  transform: translateY(40px); /** 下にずらす **/
  transition: opacity 0.8s ease, transform 0.8s ease; /** 表示アニメーション **/
}

.card_item figure.card_item_block.is-visible {
  opacity: 1 !important; /** 表示時に完全表示 **/
  transform: translateY(0); /** 元位置に戻す **/
}

/* 遅延アニメーション設定(figureに指定) */ /** 表示タイミングをずらす **/
.card_item figure.card_item_block:nth-child(1) {
  transition-delay: 0s; /** 最初すぐ表示 **/
}
.card_item figure.card_item_block:nth-child(2) {
  transition-delay: 0.2s; /** 2番目遅延0.2秒 **/
}
.card_item figure.card_item_block:nth-child(3) {
  transition-delay: 0.4s; /** 3番目遅延0.4秒 **/
}

/* 続きを読むボタン */
.card_item .more-link {
	display: block; /** ブロック表示 **/
	border: 1px #028cd4 solid; /** 青枠 **/
	padding: 12px 24px; /** 内側余白 **/
	line-height: 26px; /** 行の高さ **/
	margin: 30px 0 64px; /** 上下の余白調整 **/
	box-sizing: border-box; /** 枠込み計算 **/
	clear: both; /** 回り込み解除 **/
	color: #444; /** テキスト色 **/
	font-size: 14px; /** フォントサイズ **/
	border-radius: 10px; /** 角丸ボタン **/
	text-align: center; /** 中央寄せ **/
	width:100%; /** 幅いっぱい **/
}

.card_item .more-link:hover {
	background: #028cd4; /** 背景青 **/
	color: #fff !important; /** テキスト白 **/
	text-decoration: none; /** 下線除去 **/
}

6 完成イメージ

ふわっと表示する1カラム用のサービス紹介カード

サービス紹介カード

7 代用プラグイン

似たような効果をプラグインで実現したい場合は以下も検討できます:

  • Animate It!(スクロールアニメーション用)
  • Scroll Triggered Animations(要素出現アニメーション)

8 まとめ

この実装により、1カラムの固定ページでカードをふわっとアニメーション表示させることができます。
シンプルかつ軽量な IntersectionObserver を使用しており、他のページには一切影響を与えません。