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

HubSpot CMS:情報をスマートに整理する「カルーセルカードモジュール」

Webサイトで複数のサービスや事例を紹介する際、縦に長く並べすぎるとユーザーの離脱を招くことがあります。今回解説する「カルーセルカードモジュール」は、複数のカード型コンテンツを横にスライド表示させることで、限られたスペースでも多くの情報をストレスなく伝えることができます。

Demo Video

Detail

Webサイトで複数のサービスや事例を紹介する際、縦に長く並べすぎるとユーザーの離脱を招くことがあります。今回解説する「カルーセルカードモジュール」は、複数のカード型コンテンツを横にスライド表示させることで、限られたスペースでも多くの情報をストレスなく伝えることができます。

1. 目的

本モジュールの主な目的は、「情報の整理」と「直感的な操作性の両立」です。

  • スペースの有効活用: 多くのコンテンツ(事例や機能紹介など)を、1つのセクション内でスライド形式にまとめて表示できます。
  • 一貫したデザイン管理: 全体的なスタイルを一括管理しつつ、各カードの内容(画像、タイトル、説明文)を個別に設定可能です。
  • マルチデバイスへの最適化: 画面幅に応じて、PCなら複数枚、スマホなら1枚といったように表示数を自動で調整します。

2. ユースケース

  • サービス・機能紹介: 複数の主要機能をカード形式で並べ、ユーザーが興味のある項目を横スライドで確認できるようにします。
  • お客様の声・導入事例: 信頼性を高めるための事例を複数掲載し、動きのあるスライドで読了率を高めます。
  • 最新ニュース・ブログ: 記事のサムネイルを並べて表示し、サイト内の回遊を促すナビゲーションとして活用します。

3. 実装ステップ

デザインマネージャーでの設定から、編集画面での運用までの手順です。

ステップ1:コードの適用

デザインマネージャーで新規モジュールを作成し、公開されているソースコードをHTML/HubL、CSS、JSの各該当箇所へそのままコピー&ペーストして公開します。

ステップ2:基本情報とスタイルの設定

ページ編集画面でモジュールを配置し、セクション全体の見出しや、タイトル・テキストの色、フォントサイズなどをブランドに合わせて指定します。

ステップ3:カードコンテンツの追加

「cards」グループから、必要な数だけ項目を追加します。各カードごとに「画像」「タイトル」「説明文(リッチテキスト形式)」を入力します。

ステップ4:挙動のカスタマイズ

「自動再生(autoplay)」の有効化や、スライドの切り替えスピード、枠線の有無などをスイッチや数値入力で調整して完了です。

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

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

1. fields.json

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

[
 {
  "allow_new_line": false,
  "display_width": null,
  "id": "f828e942-d88b-6872-99aa-7e6839a2ba4a",
  "label": "section_title",
  "locked": false,
  "name": "section_title",
  "required": false,
  "type": "text"
 },
 {
  "default": {
   "color": null,
   "opacity": null
  },
  "display_width": null,
  "id": "23d16879-569c-2624-b906-6ae2371a442f",
  "label": "title_color",
  "locked": false,
  "name": "title_color",
  "required": false,
  "type": "color"
 },
 {
  "display": "text",
  "display_width": null,
  "id": "bf18e844-9553-d75c-fe55-7e0c1a65fe9d",
  "label": "title_font_size",
  "locked": false,
  "name": "title_font_size",
  "required": false,
  "step": 1,
  "type": "number"
 },
 {
  "children": [
   {
    "default": {
     "size_type": "auto",
     "src": "",
     "alt": null,
     "loading": "lazy"
    },
    "display_width": null,
    "id": "0c514272-f096-02d4-33c1-791a40fe2d9f",
    "label": "Image",
    "locked": false,
    "name": "image",
    "required": false,
    "resizable": true,
    "responsive": true,
    "show_loading": false,
    "type": "image"
   },
   {
    "allow_new_line": false,
    "display_width": null,
    "id": "1f453c47-b6a2-a51a-f8d7-dc5248114ba0",
    "label": "title",
    "locked": false,
    "name": "title",
    "required": false,
    "type": "text"
   },
   {
    "display_width": null,
    "id": "456812f3-1652-0fff-f563-f8787f2efbcc",
    "label": "description",
    "locked": false,
    "name": "description",
    "required": false,
    "type": "richtext"
   }
  ],
  "default": [],
  "display_width": null,
  "expanded": false,
  "group_occurrence_meta": null,
  "id": "004e3419-0e40-def3-93c0-bf008f14bb26",
  "label": "cards",
  "locked": false,
  "name": "cards",
  "occurrence": {},
  "required": false,
  "tab": "CONTENT",
  "type": "group"
 },
 {
  "default": {
   "color": null,
   "opacity": null
  },
  "display_width": null,
  "id": "f577bff8-1c57-1000-f2b9-0297e618fb2a",
  "label": "card_title_color",
  "locked": false,
  "name": "card_title_color",
  "required": false,
  "type": "color"
 },
 {
  "default": {
   "color": null,
   "opacity": null
  },
  "display_width": null,
  "id": "33968af4-9a30-8270-1df2-5ff36ebcca38",
  "label": "card_descriotion_color",
  "locked": false,
  "name": "card_descriotion_color",
  "required": false,
  "type": "color"
 },
 {
  "display": "text",
  "display_width": null,
  "id": "9c9f49bb-5a85-c6b6-395b-c8577fffac7b",
  "label": "card_description_font_size",
  "locked": false,
  "name": "card_description_font_size",
  "required": false,
  "step": 1,
  "type": "number"
 },
 {
  "default": {
   "color": null,
   "opacity": null
  },
  "display_width": null,
  "id": "7152aefd-c5cc-1ad9-9025-c6f55715d19d",
  "label": "border_color",
  "locked": false,
  "name": "border_color",
  "required": false,
  "type": "color"
 },
 {
  "display": "text",
  "display_width": null,
  "id": "1c170b7c-6ba3-2f81-7881-884f1b780fc9",
  "label": "border_width",
  "locked": false,
  "name": "border_width",
  "required": false,
  "step": 1,
  "type": "number"
 },
 {
  "default": false,
  "display": "checkbox",
  "display_width": null,
  "id": "624857cf-7d81-5530-10aa-72b51715b231",
  "label": "autoplay",
  "locked": false,
  "name": "autoplay",
  "required": false,
  "type": "boolean"
 }
]

Source Code

HTML
{% if module.section_title %}
<div class="hs-carousel-section">
  <h2 class="hs-carousel-title" style="color: {{ module.title_color.color }}; font-size: {{ module.title_font_size }}px;">
    {{ module.section_title }}
  </h2>
  
  <div class="hs-carousel-container">
    <button class="hs-carousel-nav hs-carousel-nav-prev" aria-label="前へ">
      <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
        <path d="M15 18L9 12L15 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
      </svg>
    </button>
    
    <div class="hs-carousel-wrapper">
      <div class="hs-carousel-track">
        {% for card in module.cards %}
        <div class="hs-carousel-card" style="border-color: {{ module.border_color.color }}; border-width: {{ module.border_width }}px;">
          {% if card.image.src %}
          <div class="hs-card-image-wrapper">
            <img src="{{ card.image.src }}" alt="{{ card.image.alt }}" class="hs-card-image">
          </div>
          {% endif %}
          
          <div class="hs-card-content">
            {% if card.title %}
            <h3 class="hs-card-title" style="color: {{ module.card_title_color.color }}; font-size: {{ module.card_title_font_size }}px;">
              {{ card.title }}
            </h3>
            {% endif %}
            
            {% if card.description %}
            <p class="hs-card-description" style="color: {{ module.card_description_color.color }}; font-size: {{ module.card_description_font_size }}px;">
              {{ card.description }}
            </p>
            {% endif %}
          </div>
        </div>
        {% endfor %}
      </div>
    </div>
    
    <button class="hs-carousel-nav hs-carousel-nav-next" aria-label="次へ">
      <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
        <path d="M9 18L15 12L9 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
      </svg>
    </button>
  </div>
  
  <div class="hs-carousel-dots"></div>
</div>
{% endif %}
CSS
.hs-carousel-section {
  max-width: 1200px;
  margin: 0 auto;
  padding: 40px 20px;
  box-sizing: border-box;
}
.hs-carousel-title {
  text-align: center;
  margin: 0 0 40px 0;
  font-weight: bold;
  line-height: 1.2;
}
.hs-carousel-container {
  position: relative;
  padding: 0 60px;
  width: 100%;
  box-sizing: border-box;
  margin: 0 auto;
}
.hs-carousel-wrapper {
  overflow: hidden;
  margin-bottom: 30px;
  width: 100%;
  position: relative;
}
.hs-carousel-track {
  display: flex;
  transition: transform 0.5s ease;
  will-change: transform;
}
.hs-carousel-card {
  flex: 0 0 calc(33.333% - 16px);
  background: #fff;
  border-radius: 12px;
  border-style: solid;
  overflow: hidden;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  transition: transform 0.3s ease, box-shadow 0.3s ease;
  margin-right: 24px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
}
.hs-carousel-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}
.hs-card-image-wrapper {
  width: 100%;
  height: 200px;
  overflow: hidden;
  background: #f5f5f5;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.hs-card-image {
  width: 100%;
  height: 100%;
  object-fit: contain;
  padding: 20px;
  display: block;
}
.hs-card-content {
  padding: 24px;
  flex-grow: 1;
  display: flex;
  flex-direction: column;
}
.hs-card-title {
  margin: 0 0 12px 0;
  font-weight: 600;
  line-height: 1.4;
}
.hs-card-description {
  margin: 0;
  line-height: 1.6;
}
.hs-carousel-nav {
  position: absolute !important;
  top: 50% !important;
  transform: translateY(-50%) !important;
  background: #fff !important;
  border: 2px solid #ddd !important;
  border-radius: 50% !important;
  width: 48px !important;
  height: 48px !important;
  min-width: 48px !important;
  min-height: 48px !important;
  max-width: 48px !important;
  max-height: 48px !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  cursor: pointer !important;
  transition: all 0.3s ease !important;
  z-index: 100 !important;
  color: #333 !important;
  padding: 0 !important;
  margin: 0 !important;
  font-size: 16px !important;
  line-height: 1 !important;
  text-decoration: none !important;
  outline: none !important;
  box-sizing: border-box !important;
  flex-shrink: 0 !important;
}
.hs-carousel-nav:hover {
  background: #f5f5f5 !important;
  border-color: #999 !important;
}
.hs-carousel-nav-prev {
  left: 0 !important;
}
.hs-carousel-nav-next {
  right: 0 !important;
}
.hs-carousel-dots {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-top: 20px;
}
.hs-carousel-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: #ddd;
  border: none;
  cursor: pointer;
}
.hs-carousel-dot.active {
  background: #fed500;
  width: 32px;
  border-radius: 6px;
}
@media (max-width: 1024px) {
  .hs-carousel-card {
    flex: 0 0 calc(50% - 12px);
  }
}
@media (max-width: 768px) {
  .hs-carousel-card {
    flex: 0 0 calc(100% - 24px);
  }
}
Javascript

FAQ

カードは何枚まで追加できますか?

システム上の制限はありませんが、ユーザーの閲覧しやすさを考慮し、5〜10枚程度に収めるのが一般的です。

スライドが切り替わるスピードを変更できますか?

可能です。コード内の設定値を調整することで、スライドが切り替わる間隔をカスタマイズできます。

特定のデバイスだけで非表示にできますか?

HubSpot標準の「表示設定」機能を組み合わせることで、モバイルのみ、あるいはデスクトップのみといった出し分けが可能です。