移至主內容

用Swiper做出產品圖片Slide的模板

2025/12/8 , written by Wanding

前言

在電商網站或產品展示頁面中,如何讓訪客清楚瀏覽多張產品圖片是個重要課題。一個好的圖片展示方式不僅能提升使用者體驗,也能讓產品更有質感。本文將教你使用 **Swiper.js** 搭配 Drupal 的 Twig 模板,打造專業的產品圖片輪播效果。

什麼是Swiper

Swiper 是目前最流行的觸控滑動函式庫之一,具有以下優勢:

  • 📱 完美支援行動裝置觸控滑動
  • 🎨 高度客製化,樣式自由調整
  • ⚡ 效能優異,檔案輕量
  • 🔧 功能豐富(縮圖連動、循環播放、自動播放等)

本文將實現的目標

  • ✅ 大圖展示區域,左右箭頭切換
  • ✅ 縮圖導航列,點擊即可切換主圖
  • ✅ 響應式設計,自動適應手機、平板、電腦
  • ✅ 手機版滿版顯示,提供最佳瀏覽體驗

Step1: 建立產品內容類型

首先,我們需要建立一個專門用來展示產品的內容類型。

1.1建立Content Type

  1. 登入 Drupal 後台
  2. 前往 Structure → Content types → Add content type
  3. 填寫資料:
    • Name: Product(產品)
    • Machine name: product(會自動產生,請確認是這個名稱)
  4. 點擊 Save and manage fields

1.2 新增圖片欄位

  1. 在欄位管理頁面,點擊 Add field
  2. 選擇 Reference → Image
  3. 填寫欄位設定:
    • Label: Product Images(產品圖片)
    • Machine name: field_images(重要!程式碼會用到)
  4. 在下一頁設定:
    • Number of values: Unlimited(無限制)
    • File directory: product_images(選填,方便管理)
    • Maximum upload size: 依需求設定(建議 5MB)
  5. 儲存設定

Step 2: 建立 Twig 模板檔案

2.1 找到模板資料夾

前往你的主題資料夾,通常路徑為 themes/custom/your_theme/templates/node

2.2 建立 node--product.html.twig

💡 命名規則說明:

  • node-- 是固定前綴
  • product 對應內容類型的機器名稱
  • 使用兩個減號 --
  • 副檔名必須是 .html.twig

2.3 貼上完整程式碼

將以下程式碼複製到檔案中:

  {# 產品圖片 Swiper 模板 - 含主圖箭頭與縮圖導航 #}

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />

<style>
/* =========================
   全域設定
========================= */
* { 
    box-sizing: border-box; 
    margin: 0; 
    padding: 0; 
}

.card-wrapper {
    max-width: 900px;
    margin: 20px auto 60px;
    padding: 0 15px;
}

.card {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
    grid-gap: 40px;
}

/* 平板以下改為單欄 */
@media (max-width: 992px) {
    .card { 
        grid-template-columns: 1fr; 
    }
}

/* =========================
   主圖區域
========================= */
.mySwiper2 {
    width: 100%;
    aspect-ratio: 1 / 1;  /* 正方形 */
    border-radius: 20px;
    overflow: hidden;
    background: #f7f7f7;
    position: relative;
}

@media (max-width: 992px) {
    .mySwiper2 { 
        aspect-ratio: 4/3;  /* 平板改為 4:3 */
    }
}

.mySwiper2 .swiper-slide {
    width: 100% !important;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.mySwiper2 img {
    width: 100%;
    height: 100%;
    object-fit: contain;  /* 圖片完整顯示,不裁切 */
    display: block;
}

/* =========================
   主圖箭頭樣式
========================= */
.main-prev,
.main-next {
    color: #333;
    width: 42px;
    height: 42px;
    background: rgba(255,255,255,0.6);
    border-radius: 50%;
    box-shadow: 0 2px 6px rgba(0,0,0,0.2);
}

.main-prev::after,
.main-next::after {
    font-size: 20px;
    font-weight: bold;
}

.main-prev {
    left: 12px;
}

.main-next {
    right: 12px;
}

.mySwiper2 .swiper-button-prev,
.mySwiper2 .swiper-button-next {
    top: 50%;
    transform: translateY(-50%);
}

/* =========================
   手機版特殊處理
========================= */
@media (max-width: 600px) {
    /* 隱藏箭頭(手機上用滑動操作) */
    .main-prev,
    .main-next {
        display: none !important;
    }
    
    /* 主圖區域滿版顯示 */
    .product-imgs {
        width: 100vw;
        margin-left: calc(-50vw + 50%);
        margin-right: calc(-50vw + 50%);
    }

    .mySwiper2 {
        width: 100vw;
        margin-left: calc(-50vw + 50%);
        margin-right: calc(-50vw + 50%);
        border-radius: 26px;
        overflow: hidden;
        height: auto;
        aspect-ratio: auto;
    }

    .mySwiper2 .swiper-slide {
        height: auto !important;
        display: block;
    }

    .mySwiper2 img {
        width: 100%;
        height: auto;
        object-fit: contain;
        border-radius: 26px;
    }
}

/* =========================
   縮圖導航列
========================= */
.mySwiper {
    height: 110px;
    margin-top: 14px;
}

.mySwiper .swiper-slide {
    width: 100px !important;
    height: 100px;
    opacity: 0.4;  /* 未選中的縮圖較淡 */
    cursor: pointer;
    border-radius: 16px;
    overflow: hidden;
    transition: opacity 0.3s;
}

.mySwiper .swiper-slide-thumb-active {
    opacity: 1;  /* 選中的縮圖完全不透明 */
}

.mySwiper img {
    width: 100%;
    height: 100%;
    object-fit: cover;  /* 縮圖裁切填滿 */
}

/* 手機版縮圖調整 */
@media (max-width: 600px) {
    .mySwiper {
        height: 90px;
        margin-top: 12px;
        padding: 0 15px;
    }

    .mySwiper .swiper-slide {
        width: 85px !important;
        height: 85px !important;
        border-radius: 14px;
    }
}

/* =========================
   右側產品資訊區域
========================= */
.product-content {
    padding: 20px 0;
}

.product-content h1 {
    font-size: 28px;
    margin-bottom: 20px;
    color: #333;
}

.product-content .body-content {
    line-height: 1.8;
    color: #666;
}
</style>

<div class="card-wrapper">
    <div class="card">

        <!-- 左側:主圖 + 縮圖 -->
        <div class="product-imgs">

            <!-- 主圖輪播 -->
            <div class="swiper mySwiper2">
                <!-- 左右箭頭 -->
                <div class="swiper-button-prev main-prev"></div>
                <div class="swiper-button-next main-next"></div>

                <div class="swiper-wrapper">
                    {% for img in node.field_images %}
                        {% set uri = img.entity.uri.value %}
                        <div class="swiper-slide">
                            <img src="{{ file_url(uri) }}" alt="{{ label }}">
                        </div>
                    {% endfor %}
                </div>
            </div>

            <!-- 縮圖導航 -->
            <div class="swiper mySwiper">
                <div class="swiper-wrapper">
                    {% for img in node.field_images %}
                        {% set uri = img.entity.uri.value %}
                        <div class="swiper-slide">
                            <img src="{{ file_url(uri) }}" alt="{{ label }} thumbnail">
                        </div>
                    {% endfor %}
                </div>
            </div>

        </div>

        <!-- 右側:產品資訊 -->
        <div class="product-content">
            <h1>{{ label }}</h1>
            {% if content.body %}
                <div class="body-content">
                    {{ content.body }}
                </div>
            {% endif %}
        </div>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>

<script>
document.addEventListener('DOMContentLoaded', function () {

    // 初始化縮圖輪播
    var thumbsSwiper = new Swiper(".mySwiper", {
        loop: false,              // 不循環播放
        spaceBetween: 10,         // 縮圖間距 10px
        slidesPerView: 5,         // 同時顯示 5 個縮圖
        freeMode: true,           // 自由滑動模式
        watchSlidesProgress: true // 監聽滑動進度
    });

    // 初始化主圖輪播
    var mainSwiper = new Swiper(".mySwiper2", {
        loop: false,              // 不循環播放
        spaceBetween: 10,         // 圖片間距
        slidesPerView: 1,         // 一次顯示 1 張
        navigation: {
            nextEl: ".main-next", // 下一張按鈕
            prevEl: ".main-prev", // 上一張按鈕
        },
        thumbs: { 
            swiper: thumbsSwiper  // 與縮圖連動
        }
    });

});
</script>

Step 3: 測試與驗證

  1. 前往 Content → Add content → Product
  2. 填寫產品標題
  3. 在 Product Images 欄位上傳 3-5 張圖片
  4. 填寫產品描述(Body 欄位)
  5. 點擊 Save
  6. 開啟網頁驗證

用Swiper做出產品圖片Slide的模板

2025/12/8 , written by Wanding

前言

在電商網站或產品展示頁面中,如何讓訪客清楚瀏覽多張產品圖片是個重要課題。一個好的圖片展示方式不僅能提升使用者體驗,也能讓產品更有質感。本文將教你使用 **Swiper.js** 搭配 Drupal 的 Twig 模板,打造專業的產品圖片輪播效果。

什麼是Swiper

Swiper 是目前最流行的觸控滑動函式庫之一,具有以下優勢:

  • 📱 完美支援行動裝置觸控滑動
  • 🎨 高度客製化,樣式自由調整
  • ⚡ 效能優異,檔案輕量
  • 🔧 功能豐富(縮圖連動、循環播放、自動播放等)

本文將實現的目標

  • ✅ 大圖展示區域,左右箭頭切換
  • ✅ 縮圖導航列,點擊即可切換主圖
  • ✅ 響應式設計,自動適應手機、平板、電腦
  • ✅ 手機版滿版顯示,提供最佳瀏覽體驗

Step1: 建立產品內容類型

首先,我們需要建立一個專門用來展示產品的內容類型。

1.1建立Content Type

  1. 登入 Drupal 後台
  2. 前往 Structure → Content types → Add content type
  3. 填寫資料:
    • Name: Product(產品)
    • Machine name: product(會自動產生,請確認是這個名稱)
  4. 點擊 Save and manage fields

1.2 新增圖片欄位

  1. 在欄位管理頁面,點擊 Add field
  2. 選擇 Reference → Image
  3. 填寫欄位設定:
    • Label: Product Images(產品圖片)
    • Machine name: field_images(重要!程式碼會用到)
  4. 在下一頁設定:
    • Number of values: Unlimited(無限制)
    • File directory: product_images(選填,方便管理)
    • Maximum upload size: 依需求設定(建議 5MB)
  5. 儲存設定

Step 2: 建立 Twig 模板檔案

2.1 找到模板資料夾

前往你的主題資料夾,通常路徑為 themes/custom/your_theme/templates/node

2.2 建立 node--product.html.twig

💡 命名規則說明:

  • node-- 是固定前綴
  • product 對應內容類型的機器名稱
  • 使用兩個減號 --
  • 副檔名必須是 .html.twig

2.3 貼上完整程式碼

將以下程式碼複製到檔案中:

  {# 產品圖片 Swiper 模板 - 含主圖箭頭與縮圖導航 #}

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />

<style>
/* =========================
   全域設定
========================= */
* { 
    box-sizing: border-box; 
    margin: 0; 
    padding: 0; 
}

.card-wrapper {
    max-width: 900px;
    margin: 20px auto 60px;
    padding: 0 15px;
}

.card {
    display: grid;
    grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr);
    grid-gap: 40px;
}

/* 平板以下改為單欄 */
@media (max-width: 992px) {
    .card { 
        grid-template-columns: 1fr; 
    }
}

/* =========================
   主圖區域
========================= */
.mySwiper2 {
    width: 100%;
    aspect-ratio: 1 / 1;  /* 正方形 */
    border-radius: 20px;
    overflow: hidden;
    background: #f7f7f7;
    position: relative;
}

@media (max-width: 992px) {
    .mySwiper2 { 
        aspect-ratio: 4/3;  /* 平板改為 4:3 */
    }
}

.mySwiper2 .swiper-slide {
    width: 100% !important;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

.mySwiper2 img {
    width: 100%;
    height: 100%;
    object-fit: contain;  /* 圖片完整顯示,不裁切 */
    display: block;
}

/* =========================
   主圖箭頭樣式
========================= */
.main-prev,
.main-next {
    color: #333;
    width: 42px;
    height: 42px;
    background: rgba(255,255,255,0.6);
    border-radius: 50%;
    box-shadow: 0 2px 6px rgba(0,0,0,0.2);
}

.main-prev::after,
.main-next::after {
    font-size: 20px;
    font-weight: bold;
}

.main-prev {
    left: 12px;
}

.main-next {
    right: 12px;
}

.mySwiper2 .swiper-button-prev,
.mySwiper2 .swiper-button-next {
    top: 50%;
    transform: translateY(-50%);
}

/* =========================
   手機版特殊處理
========================= */
@media (max-width: 600px) {
    /* 隱藏箭頭(手機上用滑動操作) */
    .main-prev,
    .main-next {
        display: none !important;
    }
    
    /* 主圖區域滿版顯示 */
    .product-imgs {
        width: 100vw;
        margin-left: calc(-50vw + 50%);
        margin-right: calc(-50vw + 50%);
    }

    .mySwiper2 {
        width: 100vw;
        margin-left: calc(-50vw + 50%);
        margin-right: calc(-50vw + 50%);
        border-radius: 26px;
        overflow: hidden;
        height: auto;
        aspect-ratio: auto;
    }

    .mySwiper2 .swiper-slide {
        height: auto !important;
        display: block;
    }

    .mySwiper2 img {
        width: 100%;
        height: auto;
        object-fit: contain;
        border-radius: 26px;
    }
}

/* =========================
   縮圖導航列
========================= */
.mySwiper {
    height: 110px;
    margin-top: 14px;
}

.mySwiper .swiper-slide {
    width: 100px !important;
    height: 100px;
    opacity: 0.4;  /* 未選中的縮圖較淡 */
    cursor: pointer;
    border-radius: 16px;
    overflow: hidden;
    transition: opacity 0.3s;
}

.mySwiper .swiper-slide-thumb-active {
    opacity: 1;  /* 選中的縮圖完全不透明 */
}

.mySwiper img {
    width: 100%;
    height: 100%;
    object-fit: cover;  /* 縮圖裁切填滿 */
}

/* 手機版縮圖調整 */
@media (max-width: 600px) {
    .mySwiper {
        height: 90px;
        margin-top: 12px;
        padding: 0 15px;
    }

    .mySwiper .swiper-slide {
        width: 85px !important;
        height: 85px !important;
        border-radius: 14px;
    }
}

/* =========================
   右側產品資訊區域
========================= */
.product-content {
    padding: 20px 0;
}

.product-content h1 {
    font-size: 28px;
    margin-bottom: 20px;
    color: #333;
}

.product-content .body-content {
    line-height: 1.8;
    color: #666;
}
</style>

<div class="card-wrapper">
    <div class="card">

        <!-- 左側:主圖 + 縮圖 -->
        <div class="product-imgs">

            <!-- 主圖輪播 -->
            <div class="swiper mySwiper2">
                <!-- 左右箭頭 -->
                <div class="swiper-button-prev main-prev"></div>
                <div class="swiper-button-next main-next"></div>

                <div class="swiper-wrapper">
                    {% for img in node.field_images %}
                        {% set uri = img.entity.uri.value %}
                        <div class="swiper-slide">
                            <img src="{{ file_url(uri) }}" alt="{{ label }}">
                        </div>
                    {% endfor %}
                </div>
            </div>

            <!-- 縮圖導航 -->
            <div class="swiper mySwiper">
                <div class="swiper-wrapper">
                    {% for img in node.field_images %}
                        {% set uri = img.entity.uri.value %}
                        <div class="swiper-slide">
                            <img src="{{ file_url(uri) }}" alt="{{ label }} thumbnail">
                        </div>
                    {% endfor %}
                </div>
            </div>

        </div>

        <!-- 右側:產品資訊 -->
        <div class="product-content">
            <h1>{{ label }}</h1>
            {% if content.body %}
                <div class="body-content">
                    {{ content.body }}
                </div>
            {% endif %}
        </div>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>

<script>
document.addEventListener('DOMContentLoaded', function () {

    // 初始化縮圖輪播
    var thumbsSwiper = new Swiper(".mySwiper", {
        loop: false,              // 不循環播放
        spaceBetween: 10,         // 縮圖間距 10px
        slidesPerView: 5,         // 同時顯示 5 個縮圖
        freeMode: true,           // 自由滑動模式
        watchSlidesProgress: true // 監聽滑動進度
    });

    // 初始化主圖輪播
    var mainSwiper = new Swiper(".mySwiper2", {
        loop: false,              // 不循環播放
        spaceBetween: 10,         // 圖片間距
        slidesPerView: 1,         // 一次顯示 1 張
        navigation: {
            nextEl: ".main-next", // 下一張按鈕
            prevEl: ".main-prev", // 上一張按鈕
        },
        thumbs: { 
            swiper: thumbsSwiper  // 與縮圖連動
        }
    });

});
</script>

Step 3: 測試與驗證

  1. 前往 Content → Add content → Product
  2. 填寫產品標題
  3. 在 Product Images 欄位上傳 3-5 張圖片
  4. 填寫產品描述(Body 欄位)
  5. 點擊 Save
  6. 開啟網頁驗證