Home
>
Product
>
Template Top
>
詳細ページ

HubSpot CMS:スクロール連動アニメーションをノーコードで制御する方法

Webサイトのユーザー体験(UX)を高めるためには、コンテンツの表示に合わせた動きの演出が不可欠です。本記事では、HubSpot CMSの「カスタムモジュール」を用いて、プログラミングの知識がない担当者でも、編集画面から自由自在に要素を動かせるアニメーション実装手法について解説します。

Demo Video

Detail

Webサイトのユーザー体験(UX)を高めるためには、コンテンツの表示に合わせた動きの演出が不可欠です。本記事では、HubSpot CMSの「カスタムモジュール」を用いて、プログラミングの知識がない担当者でも、編集画面から自由自在に要素を動かせるアニメーション実装手法について解説します。

1. 実装の目的

このモジュールの目的は、特定のCSSクラスを手動で付与することなく、HubSpotのページエディター上で「どの要素を」「どのように」「いつ」動かすかを一元管理することです。

  • 運用の効率化: H1タグや画像など、アニメーションさせたい要素をリストから選択するだけで設定が完了します。
  • 一貫性のあるデザイン: サイト全体で共通のアニメーション(スライド、フェード、ポップアップ)を定義することで、デザインの統一感を保ちます。
  • パフォーマンス最適化: JavaScriptの「Intersection Observer API」を活用し、要素が画面に表示されたタイミングで効率的に実行します。

2. 想定されるユースケース

  • ヒーローエリアの演出: ページ訪問時にメインコピーを下からふわっと浮き上がらせ、第一印象を強化します。
  • スクロールによる視線誘導: 読み進める動作に合わせて、重要な図解や補足テキストを左右からスライドインさせ、読了率を高めます。
  • アクションの強調: お問い合わせボタンやバナーに「ポップアップ」の動きを加え、クリックを促します。
  • 複数要素の順次表示: 複数のカード型レイアウトに対して、「Delay(遅延)」をずらして設定することで、リズミカルな表示演出を行います。

3. 実装と設定手順

ステップ1:新規モジュールの作成

  1. HubSpotのメニューから [マーケティング] > [デザインマネージャー] を開きます。
  2. 左側のファイルツリーで右クリックし、[新しいファイル] を選択します。
  3. タイプとして [モジュール] を選択し、利用する場所(ランディングページ、ブログなど)にチェックを入れます。
  4. モジュールに名前(例:animation_controller)を付けて作成します。

ステップ2:コードの貼り付け

作成したモジュールのエディター右側にある各セクションに、ヘルプページや仕様書に記載されたコードをコピー&ペーストします。

  • HTML/HubL: 編集画面の入力をJSに渡すためのループ処理を記述します。
  • CSS: アニメーションの型(@keyframes)を記述します。
  • JavaScript: スクロール検知(IntersectionObserver)のロジックを記述します。

ステップ3:CMSページへの配置

  1. アニメーションを適用したい [ページ編集画面] を開きます。
  2. 左側のパネルから、ステップ1で作成したモジュールを検索し、ページ内の任意の場所(フッター付近など)にドラッグ&ドロップします。

ステップ4:アニメーションの詳細設定

配置したモジュールの編集パネルにある「anim_settings」から、具体的な動きを設定します。

  1. ターゲットの選択 (target_selector):
    ドロップダウンから対象(例:h2, imgなど)を選択します。
  2. アニメーション種別の指定 (anim_type):
    「slide-in(スライド)」や「fade-in(フェード)」などを選択します。
  3. 方向と時間の詳細設定:
    • direction: 開始方向(例:down を選ぶと下から上へ移動)を指定します。
    • duration: アニメーション完了までの秒数(例:1s)を入力します。
    • delay: 画面に入ってから動き出すまでの待ち時間を入力します。

4. 判定と実行の仕組み

本モジュールは、以下のフローで自動実行されます。

  • 自動除外: ヘッダーやフッター内の要素は、UXを損なわないようスクリプト側で自動的に対象外として判定します。
  • 1回限りの実行: 要素が画面内に10%以上入ったことを検知するとアニメーションが発動し、一度実行されたら監視を終了するため、ページ負荷を最小限に抑えます。
  • ノーコード運用: 一度このモジュールを配置すれば、以降はコードを一行も書かずにサイト全体に動きをつけることが可能です。

モジュールのソースコード

HubSpotのDesign Managerで「新規モジュール」を作成し、以下のコードをそれぞれの箇所に貼り付けてください。

1. fields.json

フィールド定義です。繰り返しフィールド(Items)と、スタイル設定用フィールド(Styles)で構成されています。

[
 {
  "children": [
   {
    "choices": [
     [ "h1", "H1" ], [ "h2", "H2" ], [ "h3", "H3" ], [ "h4", "H4" ],
     [ "h5", "H5" ], [ "h6", "H6" ], [ "p", "p" ], [ "span", "span" ],
     [ "div", "div" ], [ "li", "list" ], [ "img", "image" ], [ "setion", "section" ]
    ],
    "display": "select",
    "display_width": null,
    "id": "6b6e5314-9832-c18b-b7f1-e5ab1052fabb",
    "label": "target_selector",
    "locked": false,
    "multiple": false,
    "name": "target_selector",
    "preset": null,
    "reordering_enabled": true,
    "required": false,
    "type": "choice"
   },
   {
    "choices": [
     [ "slide-in", "slide-in" ], [ "slide-out", "slide-out" ],
     [ "scale-up", "scale-up" ], [ "wave", "wave" ],
     [ "bounce", "bounce" ], [ "scale-down", "scale-down" ], [ "pop-up", "pop-up" ]
    ],
    "display": "select",
    "display_width": null,
    "id": "d604cb29-9753-6dc8-fd76-e5828e86f0d2",
    "label": "anim_type",
    "locked": false,
    "multiple": false,
    "name": "anim_type",
    "preset": null,
    "reordering_enabled": true,
    "required": false,
    "type": "choice"
   },
   {
    "choices": [
     [ "down", "上から" ], [ "up", "下から" ],
     [ "left", "左から" ], [ "right", "右から" ], [ "none", "なし" ]
    ],
    "display": "select",
    "display_width": null,
    "id": "a7c1f435-7a80-f31b-5c9e-b827edf28bc8",
    "label": "direction",
    "locked": false,
    "multiple": false,
    "name": "direction",
    "preset": null,
    "reordering_enabled": true,
    "required": false,
    "type": "choice"
   },
   {
    "display": "text",
    "display_width": null,
    "id": "c15cf622-810b-0753-bc04-211167da8095",
    "label": "duration",
    "locked": false,
    "name": "duration",
    "required": false,
    "step": 1,
    "type": "number"
   },
   {
    "display": "text",
    "display_width": null,
    "id": "72e19799-ddd8-060f-4955-5ecdcd781bd9",
    "label": "delay",
    "locked": false,
    "name": "delay",
    "required": false,
    "step": 1,
    "type": "number"
   }
  ],
  "default": [],
  "display_width": null,
  "expanded": false,
  "group_occurrence_meta": null,
  "id": "f1529db5-e7c4-bba2-3b9a-e69444442236",
  "label": "anim_settings",
  "locked": false,
  "name": "anim_settings",
  "occurrence": {},
  "required": false,
  "tab": "CONTENT",
  "type": "group"
 }
]

Source Code

HTML
{# アニメーション設定をJavaScriptに渡す #}
<script>
  window.hsAnimConfig = window.hsAnimConfig || [];
  
  {% if module.anim_settings %}
    {% for item in module.anim_settings %}
      window.hsAnimConfig.push({
        selector: "{{ item.target_selector }}",
        type: "{{ item.anim_type }}",
        direction: "{{ item.direction|default('none') }}",
        duration: "{{ item.duration|default(1) }}s",
        delay: "{{ item.delay|default(0) }}s"
      });
    {% endfor %}
  {% endif %}
  
  console.log('HubSpot Animation Config:', window.hsAnimConfig);
</script>
CSS
/* 基本設定 */
.js-anim-ready {
  opacity: 0 !important;
}

/* アニメーション実行中 */
.js-anim-active {
  opacity: 1 !important;
}

/* === スライドイン === */
@keyframes slideInFromTop {
  from { opacity: 0; transform: translateY(-50px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes slideInFromBottom {
  from { opacity: 0; transform: translateY(50px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes slideInFromLeft {
  from { opacity: 0; transform: translateX(-50px); }
  to { opacity: 1; transform: translateX(0); }
}
@keyframes slideInFromRight {
  from { opacity: 0; transform: translateX(50px); }
  to { opacity: 1; transform: translateX(0); }
}

/* === スライドアウト === */
@keyframes slideOutToTop {
  from { opacity: 1; transform: translateY(0); }
  to { opacity: 0; transform: translateY(-50px); }
}
@keyframes slideOutToBottom {
  from { opacity: 1; transform: translateY(0); }
  to { opacity: 0; transform: translateY(50px); }
}

/* === その他のアニメーション === */
@keyframes scaleUp {
  from { opacity: 0; transform: scale(0.5); }
  to { opacity: 1; transform: scale(1); }
}
@keyframes scaleDown {
  from { opacity: 0; transform: scale(1.5); }
  to { opacity: 1; transform: scale(1); }
}
@keyframes wave {
  0% { opacity: 0; transform: translateX(-20px) rotate(0deg); }
  50% { opacity: 0.5; transform: translateX(10px) rotate(2deg); }
  100% { opacity: 1; transform: translateX(0) rotate(0deg); }
}
@keyframes bounce {
  0% { opacity: 0; transform: translateY(50px); }
  50% { opacity: 1; transform: translateY(-10px); }
  100% { opacity: 1; transform: translateY(0); }
}
@keyframes popUp {
  from { opacity: 0; transform: translateY(20px) scale(0.8); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}
Javascript

FAQ

アニメーションを適用したい要素ごとに、新しくモジュールを配置する必要はありますか?

いいえ、その必要はありません。 このモジュールは、編集パネル内の「anim_settings」から設定をリスト形式で追加できる仕組みになっています。1つのモジュール内で「H2タグは下からスライド」「画像は1秒遅らせてポップアップ」というように、複数の異なるターゲット設定を一括で管理・運用することが可能です。

ページを表示した瞬間に、すべての要素が動き出してしまうことはありませんか?

このモジュールは「Intersection Observer API」という仕組みを活用しており、要素が画面内に10%以上入ったタイミングを検知してアニメーションを実行します。スクロールに合わせて必要なタイミングで動き出すため、ユーザーの閲覧動作に合わせた自然な演出が可能です。

特定のエリア(ヘッダーやフッターなど)にある要素を動かしたくない場合は、個別に設定が必要ですか?

UX(ユーザー体験)を損なわないよう、スクリプト側でヘッダーやフッター内の要素を自動的に判別し、アニメーションの対象外として処理する機能が備わっています。そのため、運用者はサイト共通エリアへの影響を気にすることなく、メインコンテンツ内の要素に対してノーコードで設定を行うことができます。