🔍 コレクション/検索中級
コレクション商品のバリアント付き一覧表
コレクション内の全商品をバリアント単位の表形式で表示し、各行から直接カートに追加できるセクション。商品画像、説明、SKU、オプション、価格を一覧化して、B2B 向け注文フローや大量購入シーンに対応する。
用途
コレクションページで複数バリアントを持つ商品(色・サイズ等)を整理して表示したいとき。特に卸売・業務用など、複数バリアントからの一括選定と追加が必要なシーンに最適。
設置場所
sections/single-collection.liquid に配置し、テーマカスタマイザーでコレクション選択セクションとして呼び出す。collection.liquid テンプレートの本体部分に `{% section 'single-collection' %}` で組み込む。
注意点
商品オプションが3個以上ある場合は、table 構造が横に膨らんで可読性が低下するため、スクロール対応や折り畳みに書き換える必要がある。バリアント画像ではなく商品の featured_image のみ表示されるため、各バリアントに対応する別画像が必要なら metafield で画像 URL を持たせて追加実装する。重量(weight)フィールドが未設定だと 'N/A' が表示されるため、商品作成時に各バリアントの重量を正確に入力しておく前提。
コード
196 行 / liquid{% assign collection_products = section.settings.collection.products %}
{% if collection_products.size > 0 %}
<h1 class="sticky-header">
All Categories >
{{ section.settings.collection.title }} ({{ collection_products.size }}
{{ collection_products.size | pluralize: 'product', 'products' }})
</h1>
<div class="product-collection" style="font-family: Arial, sans-serif;">
{% for product in collection_products %}
<div class="product-container">
<span id="{{ product.handle }}" class="hash-handle"></span>
<h3 class="product-title">{{ product.title }}</h3>
<p class="product-description">{{ product.description | strip_html | truncatewords: 30 }}</p>
<div class="product-details">
<div class="image-placeholder">
{% if product.featured_image %}
{{ product.featured_image | image_url: width: 100 | image_tag: alt: product.featured_image.alt }}
{% endif %}
</div>
<table class="variant-table">
<thead>
<tr>
<th class="desktop-only">SKU</th>
<th class="desktop-only">{{ product.options[0] }}</th>
{% if product.options[1] %}
<th class="desktop-only">{{ product.options[1] }}</th>
{% endif %}
<th>Model</th>
<th class="desktop-only">Net Weight</th>
<th>Each</th>
<th>Buy</th>
</tr>
</thead>
<tbody>
{% for variant in product.variants %}
<tr class="variant-row">
<td class="desktop-only">{{ variant.sku }}</td>
<td class="desktop-only">{{ variant.option1 }}</td>
{% if variant.option2 %}
<td class="desktop-only">{{ variant.option2 }}</td>
{% endif %}
<td>{{ variant.title }}</td>
<td class="desktop-only">{{ variant.weight | default: 'N/A' }}g</td>
<td>{{ variant.price | money }}</td>
<td>
<form class="add-to-cart-form" method="post" action="/cart/add">
<input type="hidden" name="id" value="{{ variant.id }}">
<input min="1" type="number" id="quantity" name="quantity" value="1">
<input type="submit" value="Add to cart" class="add-button">
<input type="submit" value="Added!" class="added-button" disabled>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endfor %}
</div>
{% endif %}
{% stylesheet %}
.desktop-only {
display: none;
}
@media (min-width: 768px) {
.desktop-only {
display: table-cell;
}
}
.product-collection {
font-family: Arial, sans-serif;
}
.collection-title {
font-size: 24px;
margin-bottom: 10px;
}
.product-count {
font-size: 14px;
margin-bottom: 20px;
}
.product-container {
margin-bottom: 20px;
padding: 10px;
position: relative;
}
.hash-handle {
visibility: hidden;
top: -35px;
position: absolute;
}
.product-title {
font-size: 18px;
color: green;
}
.product-description {
font-size: 12px;
}
.product-details {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.image-placeholder {
width: 100px;
height: 100px;
margin-right: 10px;
}
.image-placeholder img {
width: 100%;
height: auto;
object-fit: cover;
}
.variant-table {
width: 100%;
border-collapse: collapse;
}
th,
td {
text-align: left; /* Left-align headers and cells */
padding: 4px; /* Tighter line height */
font-size: 12px;
}
.variant-row:hover {
background-color: #fff5b1; /* Pale yellow background on hover */
}
.add-to-cart-form input[type='number'] {
width: 2rem;
}
.added-button {
display: none;
}
{% endstylesheet %}
{% javascript %}
document.addEventListener('DOMContentLoaded', function () {
// Dynamically add items to the cart without reloading the page
document.querySelectorAll('.add-to-cart-form').forEach((form) => {
form.addEventListener('submit', function (event) {
event.preventDefault();
const formData = new FormData(form);
fetch(window.Shopify.routes.root + 'cart/add.js', {
method: 'POST',
body: formData,
})
.then((response) => response.json())
.then((data) => {
form.querySelector('.add-button').style.display = 'none';
form.querySelector('.added-button').style.display = 'inline-block';
setTimeout(() => {
form.querySelector('.added-button').style.display = 'none';
form.querySelector('.add-button').style.display = 'inline-block';
}, 2000);
// Update the cart item count in the page header
fetch(window.Shopify.routes.root + 'cart.js', {
method: 'GET',
})
.then((response) => response.json())
.then((cart) => {
document.querySelector('#cart-item-count').textContent = cart.items.length;
});
})
.catch((error) => {
console.error('Error adding item to cart:', error);
});
});
});
});
{% endjavascript %}
{% schema %}
{
"name": "Single Collection View",
"class": "section",
"tag": "section",
"disabled_on": {
"groups": ["header", "footer"]
},
"settings": [
{
"type": "collection",
"id": "collection",
"label": "Collection"
}
]
}
{% endschema %}
出典・ライセンス
- Repository:
- https://github.com/Shopify/mcliquid-theme
- License:
- MIT
このコードは Shopify 著作の MIT ライセンスソースです。 原本の著作権は Shopify が保有します。日本語訳は ALSEL によるものです。
関連項目
🔍 コレクション/検索初級
ページネーションの表示
ページネーションUI(前へ・次へ、ページ番号)を paginate オブジェクトから描画するスニペット。デフォルトのページネーション形式で複数ページに分割したコンテンツをナビゲートできる。
📁 shopify-code-snippets·MIT·6 行
🔍 コレクション/検索初級
ページネーションの現在位置表示
コレクションや検索結果の一覧ページで、現在のページ番号と全ページ数を表示する。Shopify の多言語対応翻訳キーを使用して、言語ごとに自動で表記を切り替える。
📁 shopify-code-snippets·MIT·6 行
🔍 コレクション/検索中級
検索結果のペジネーション比較
検索結果を paginate タグで複数パターン分割して表示するテンプレート。デフォルトペジネーションと window_size:1 オプション指定の両方の書き方を示しており、ページネーション動作の違いを検証するサンプルコード。
📁 theme-tools·MIT·12 行
🔍 コレクション/検索初級
検索結果のページネーション設定
検索結果を paginate タグでページ分割し、複数の window_size 設定を並べて出力する方法。28件単位のペーグネーションと、ウィンドウサイズを明示的に指定した設定の2パターンを示している。
📁 theme-tools·MIT·12 行
🔍 コレクション/検索初級
コレクションページの商品ギャラリー
コレクション内の商品を3列のテーブルレイアウトで表示するテンプレート。各商品にサムネイル、タイトル、価格(セール時は定価を取消線)を表示し、ページネーションに対応する。
📁 liquid·MIT·20 行
🔍 コレクション/検索初級
コレクションページの商品一覧
コレクション内の商品を一覧表示し、商品画像・タイトル・説明文・価格帯をカード状に並べる。ページネーション機能で20件ごとに分割表示する。
📁 liquid·MIT·23 行