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


Webサイトのユーザー体験(UX)を高めるためには、コンテンツの表示に合わせた動きの演出が不可欠です。本記事では、HubSpot CMSの「カスタムモジュール」を用いて、プログラミングの知識がない担当者でも、編集画面から自由自在に要素を動かせるアニメーション実装手法について解説します。
このモジュールの目的は、特定のCSSクラスを手動で付与することなく、HubSpotのページエディター上で「どの要素を」「どのように」「いつ」動かすかを一元管理することです。
作成したモジュールのエディター右側にある各セクションに、ヘルプページや仕様書に記載されたコードをコピー&ペーストします。
配置したモジュールの編集パネルにある「anim_settings」から、具体的な動きを設定します。
本モジュールは、以下のフローで自動実行されます。
HubSpotのDesign Managerで「新規モジュール」を作成し、以下のコードをそれぞれの箇所に貼り付けてください。
フィールド定義です。繰り返しフィールド(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"
}
]{# アニメーション設定を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>/* 基本設定 */
.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; }
}いいえ、その必要はありません。 このモジュールは、編集パネル内の「anim_settings」から設定をリスト形式で追加できる仕組みになっています。1つのモジュール内で「H2タグは下からスライド」「画像は1秒遅らせてポップアップ」というように、複数の異なるターゲット設定を一括で管理・運用することが可能です。
このモジュールは「Intersection Observer API」という仕組みを活用しており、要素が画面内に10%以上入ったタイミングを検知してアニメーションを実行します。スクロールに合わせて必要なタイミングで動き出すため、ユーザーの閲覧動作に合わせた自然な演出が可能です。
UX(ユーザー体験)を損なわないよう、スクリプト側でヘッダーやフッター内の要素を自動的に判別し、アニメーションの対象外として処理する機能が備わっています。そのため、運用者はサイト共通エリアへの影響を気にすることなく、メインコンテンツ内の要素に対してノーコードで設定を行うことができます。