
Webサイトにおいて、顧客の信頼を獲得するために「導入事例」は欠かせないコンテンツです。今回解説する「導入事例カードモジュール」を使用すれば、デザインの一貫性を保ちながら、複数の成功事例をスライダー形式で美しく表示させることができます。


Webサイトにおいて、顧客の信頼を獲得するために「導入事例」は欠かせないコンテンツです。今回解説する「導入事例カードモジュール」を使用すれば、デザインの一貫性を保ちながら、複数の成功事例をスライダー形式で美しく表示させることができます。
本モジュールの主な目的は、「視覚的に優れた導入事例セクションを、専門知識がなくても直感的に構築・更新できるようにすること」です。
新規ページの作成から、提供されたコードの適用、現場での運用設定までの全工程です。
HubSpot管理画面から新しいページを立ち上げます。エディター左側のサイドバーでモジュール名を検索し、編集エリアへドラッグ&ドロップして配置します。
デザインマネージャーで新規モジュールを作成し、公開されているソースコードを、それぞれの該当箇所(HTML/HubL、JS、CSS)へそのままコピー&ペーストして保存・公開します。
コード適用後は、編集画面のサイドパネルからノーコードで詳細を調整できます。
HubSpotのDesign Managerで「新規モジュール」を作成し、以下のコードをそれぞれの箇所に貼り付けてください。
フィールド定義です。繰り返しフィールド(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"
}
]{% 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 %}
<script>
(function() {
const container = document.querySelector('.hs-carousel-section');
if (!container) return;
const track = container.querySelector('.hs-carousel-track');
const prevBtn = container.querySelector('.hs-carousel-nav-prev');
const nextBtn = container.querySelector('.hs-carousel-nav-next');
const dotsContainer = container.querySelector('.hs-carousel-dots');
const cards = container.querySelectorAll('.hs-carousel-card');
const autoplay = {{ module.autoplay|lower }};
const autoplaySpeed = {{ module.autoplay_speed || 5000 }};
let currentIndex = 0;
let autoplayInterval;
let cardsPerView = 3;
let totalSlides = 0;
function getCardsPerView() {
if (window.innerWidth <= 768) {
return 1;
} else if (window.innerWidth <= 1024) {
return 2;
}
return 3;
}
function getTotalSlides() {
return Math.ceil(cards.length / cardsPerView);
}
function createDots() {
dotsContainer.innerHTML = '';
totalSlides = getTotalSlides();
for (let i = 0; i < totalSlides; i++) {
const dot = document.createElement('button');
dot.classList.add('hs-carousel-dot');
dot.setAttribute('aria-label', 'スライド ' + (i + 1));
dot.setAttribute('data-index', i);
if (i === currentIndex) {
dot.classList.add('active');
}
dot.addEventListener('click', function() {
const index = parseInt(this.getAttribute('data-index'));
goToSlide(index);
});
dotsContainer.appendChild(dot);
}
}
function updateDots() {
const allDots = dotsContainer.querySelectorAll('.hs-carousel-dot');
allDots.forEach(function(dot, index) {
if (index === currentIndex) {
dot.classList.add('active');
} else {
dot.classList.remove('active');
}
});
}
function updateCarousel() {
cardsPerView = getCardsPerView();
totalSlides = getTotalSlides();
if (currentIndex >= totalSlides) {
currentIndex = totalSlides - 1;
}
if (currentIndex < 0) {
currentIndex = 0;
}
const cardWidth = 100 / cardsPerView;
const offset = -(currentIndex * cardWidth * cardsPerView);
track.style.transform = 'translateX(' + offset + '%)';
updateDots();
}
function goToSlide(index) {
totalSlides = getTotalSlides();
if (index >= 0 && index < totalSlides) {
currentIndex = index;
updateCarousel();
resetAutoplay();
}
}
function nextSlide() {
totalSlides = getTotalSlides();
if (currentIndex >= totalSlides - 1) {
currentIndex = 0;
} else {
currentIndex++;
}
updateCarousel();
}
function prevSlide() {
totalSlides = getTotalSlides();
if (currentIndex <= 0) {
currentIndex = totalSlides - 1;
} else {
currentIndex--;
}
updateCarousel();
}
function resetAutoplay() {
if (autoplay) {
clearInterval(autoplayInterval);
autoplayInterval = setInterval(nextSlide, autoplaySpeed);
}
}
function init() {
cardsPerView = getCardsPerView();
totalSlides = getTotalSlides();
currentIndex = 0;
createDots();
updateCarousel();
}
init();
prevBtn.addEventListener('click', function() {
prevSlide();
resetAutoplay();
});
nextBtn.addEventListener('click', function() {
nextSlide();
resetAutoplay();
});
if (autoplay) {
autoplayInterval = setInterval(nextSlide, autoplaySpeed);
}
container.addEventListener('mouseenter', function() {
if (autoplay) clearInterval(autoplayInterval);
});
container.addEventListener('mouseleave', function() {
resetAutoplay();
});
let resizeTimer;
window.addEventListener('resize', function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
const oldCardsPerView = cardsPerView;
cardsPerView = getCardsPerView();
if (oldCardsPerView !== cardsPerView) {
currentIndex = 0;
createDots();
}
updateCarousel();
}, 250);
});
})();
</script>.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:focus {
outline: 2px solid #fed500 !important;
outline-offset: 2px !important;
}
.hs-carousel-nav-prev {
left: 0 !important;
right: auto !important;
}
.hs-carousel-nav-next {
right: 0 !important;
left: auto !important;
}
.hs-carousel-nav svg {
pointer-events: none;
display: block;
width: 24px;
height: 24px;
}
.hs-carousel-nav svg path {
stroke: #333 !important;
}
.hs-carousel-dots {
display: flex;
justify-content: center;
gap: 12px;
align-items: center;
flex-wrap: wrap;
margin-top: 20px;
padding: 0;
}
.hs-carousel-dot {
width: 12px !important;
height: 12px !important;
min-width: 12px !important;
min-height: 12px !important;
max-width: 12px !important;
max-height: 12px !important;
border-radius: 50% !important;
background: #ddd !important;
border: none !important;
cursor: pointer !important;
transition: all 0.3s ease !important;
padding: 0 !important;
margin: 0 !important;
flex-shrink: 0 !important;
display: block !important;
box-sizing: border-box !important;
}
.hs-carousel-dot.active {
background: #fed500 !important;
width: 32px !important;
min-width: 32px !important;
max-width: 32px !important;
height: 12px !important;
min-height: 12px !important;
max-height: 12px !important;
border-radius: 6px !important;
}
.hs-carousel-dot:hover {
background: #bbb !important;
}
.hs-carousel-dot:hover.active {
background: #fed500 !important;
}
@media (max-width: 1024px) {
.hs-carousel-card {
flex: 0 0 calc(50% - 12px);
}
.hs-carousel-container {
padding: 0 50px;
}
}
@media (max-width: 768px) {
.hs-carousel-card {
flex: 0 0 calc(100% - 24px);
}
.hs-carousel-container {
padding: 0 50px;
}
.hs-carousel-nav {
width: 40px !important;
height: 40px !important;
min-width: 40px !important;
min-height: 40px !important;
max-width: 40px !important;
max-height: 40px !important;
}
.hs-carousel-nav svg {
width: 20px;
height: 20px;
}
}はい。画面幅に応じて自動調整されるレスポンシブ機能を内蔵しており、PCでは複数枚、スマートフォンでは1枚と、デバイスに最適な表示数に切り替わります。
可能です。コード内の設定数値を変更することで、スライドが切り替わる間隔を調整できます。
エディターの「border_width」の値を0に設定するか、枠線の色を「透明」に指定することで、枠線のないフラットなデザインに変更できます。