Liquid Snippets by ALSEL
📄 ページテンプレート中級

ブログ記事一覧ページ

ブログの記事をグリッド状に一覧表示し、タグフィルタリングと記事数カウント機能を備えたセクション。Bootstrap の Offcanvas を使ったタグ検索パネルを実装している。

用途
ストアのブログメインページで記事を複数カラム表示し、訪問者がタグで記事を絞り込めるようにしたいとき。
設置場所
sections/blog-main.liquid として保存し、ブログテンプレート(templates/blog.liquid)内で `{% section 'blog-main' %}` で呼び出す。
注意点
記事の表示件数は `limit` 設定で制御され、デモストア(ks-*.myshopify.com)では自動的に6件に固定される。タグフィルタ機能は `show_tags` 有効時のみ動作するため、テーマカスタマイザーで有効化を確認する。Offcanvas のタグリスト `blog.all_tags` はブログ内の全タグを列挙するため、未使用タグが含まれる場合は管理画面から削除する。ページネーションは `paginate` タグで実装されているため、記事が多い場合は対応ページ数を確認する。
タグ:blogarticlepaginationtag-filteroffcanvasresponsive

コード

381 行 / liquid
{% liquid
  if shop.permanent_domain contains 'ks-'
    assign limit = 6
  else
    assign limit = section.settings.limit
  endif
%}

<section 
  id="blog-main-{{ collection.id }}" 
  class="
    blog-main
    {{ section.settings.bg_color }} 
    {{ section.settings.bg_gradient }}
    {{ section.settings.text_color }}
    {{ section.settings.border_top_width | prepend: 'border-top-' }}
    {{ section.settings.border_bottom_width | prepend: 'border-bottom-' }}
    {{ section.settings.border_color }} 
    {{ section.settings.pt | prepend: 'pt-' }} 
    {{ section.settings.pb | prepend: 'pb-' }}
  "
  style="
    --bs-bg-opacity: {{ section.settings.bg_opacity | append: '%' }};
    --bs-border-opacity: {{ section.settings.border_opacity | append: '%' }};
  ">
  <div 
    class="container"
    style="max-width: {{ section.settings.container_max_width | append: 'px' }};">
    {% paginate blog.articles by limit %}
      {% if blog.articles.size == 0 %}
        <p class="alert alert-primary">
          {{ 'general.blog.empty' | t }}
        </p>
      {% else %}
        <div class="blog-utilities mb-4 {% unless section.settings.show_article_count %}justify-content-end{% endunless %}">
          {% if section.settings.show_article_count %}
            <p class="block-article-count small mb-0">
              {{ 'general.blog.count_articles' | t: count: blog.articles_count }}
            </p>
          {% endif %}
          {% if section.settings.show_tags %}
            <button 
              class="btn btn-sm mx px-4 mx-2 {{ section.settings.tags_btn_color }}" 
              type="button" 
              data-bs-toggle="offcanvas" 
              data-bs-target="#offcanvas-blog-tags"
              aria-controls="offcanvas-blog-tags">
              <span class="d-flex align-items-center">
                {% render 'svg-icons', icon: 'tag', size: 16, class: 'me-3' %}
                {{ 'general.blog.tags_btn' | t }}
              </span>
            </button>
          {% endif %}
        </div>
        <div 
          class="
            article-list mx-n3 mx-desktop-n4 mb-0 row 
            {{ section.settings.breakpoint_mobile | prepend: 'row-cols-' }}
            {{ section.settings.breakpoint_tablet | prepend: 'row-cols-tablet-' }}
            {{ section.settings.breakpoint_desktop | prepend: 'row-cols-desktop-' }}
          "
          role="list">
          {% for article in blog.articles %}
            <div class="p-3 p-desktop-4 mb-3 mb-desktop-4" role="list-item">
              {% render 'article-card', article: article %}
            </div>
          {% endfor %}
        </div>
        {% render 'pagination', paginate: paginate %}
      {% endif %}
    {% endpaginate %}
  </div>
</section>

<div 
  id="offcanvas-blog-tags" 
  class="offcanvas offcanvas-end" 
  tabindex="-1"
  aria-labelledby="offcanvas-blog-tags-label">
  <div class="offcanvas-header">
    <h2 id="offcanvas-blog-tags-label" class="offcanvas-title">
      {{ 'general.blog.tags_title' | t }}
    </h2>
    <button class="btn-close" type="button" data-bs-dismiss="offcanvas" aria-label="{{ 'general.accessibility.close' | t }}">
      {% render 'svg-icons', icon: 'x' %}
    </button>
  </div>
  <div class="offcanvas-body p-0">
    <ul class="list-group list-group-flush" aria-labelledby="offcanvas-blog-tags-label">
      {% for tag in blog.all_tags %}
        <a 
          href="{{ blog.url }}/tagged/{{ tag | handleize }}" 
          class="list-group-item list-group-item-action {% if current_tags contains tag %}active{% endif %}">
          {{ tag | capitalize }}
        </a>
      {% endfor %}
    </ul>
    <div class="px-5 py-5">
      <a
        href="{{ blog.url }}" 
        class="btn btn-outline-primary w-100">
        {{ 'general.blog.tags_show_all' | t }}
      </a>
    </div>
  </div>
</div>

{% schema %}
{
  "name": "Blog",
  "settings": [
    {
      "type": "header",
      "content": "Styling"
    },
    {
      "type": "select",
      "id": "bg_color",
      "label": "Background color",
      "default": "bg-body",
      "options": [
        { "value": "bg-primary", "label": "Primary" },
        { "value": "bg-secondary", "label": "Secondary" },
        { "value": "bg-body", "label": "Body" },
        { "value": "bg-white", "label": "White" }
      ]
    },
    {
      "type": "range",
      "id": "bg_opacity",
      "label": "Background opacity",
      "min": 0,
      "max": 100,
      "step": 1,
      "default": 100,
      "unit": "%"
    },
    {
      "type": "select",
      "id": "bg_gradient",
      "label": "Background gradient",
      "options": [
        { "value": "bg-gradient", "label": "Yes" },
        { "value": "", "label": "No" }
      ],
      "default": ""
    },
    {
      "type": "select",
      "id": "text_color",
      "label": "Text color",
      "default": "text-body",
      "options": [
        { "value": "text-primary", "label": "Primary" },
        { "value": "text-secondary", "label": "Secondary" },
        { "value": "text-body", "label": "Body" },
        { "value": "text-white", "label": "White" }
      ]
    },
    {
      "type": "range",
      "id": "border_top_width",
      "label": "Border top width",
      "default": 0,
      "min": 0,
      "max": 16,
      "step": 1,
      "unit": "px"
    },
    {
      "type": "range",
      "id": "border_bottom_width",
      "label": "Border bottom width",
      "default": 0,
      "min": 0,
      "max": 16,
      "step": 1,
      "unit": "px"
    },
    {
      "type": "select",
      "id": "border_color",
      "label": "Border color",
      "default": "border-body",
      "options": [
        { "value": "border-primary", "label": "Primary" },
        { "value": "border-secondary", "label": "Secondary" },
        { "value": "border-body", "label": "Body" },
        { "value": "border-white", "label": "White" }
      ]
    },
    {
      "type": "range",
      "id": "border_opacity",
      "label": "Border opacity",
      "min": 0,
      "max": 100,
      "step": 1,
      "default": 100,
      "unit": "%"
    },
    {
      "type": "text",
      "id": "container_max_width",
      "label": "Container max-width (px)",
      "info": "Leave empty to use the global container width"
    },
    {
      "type": "header",
      "content": "General"
    },
    {
      "type": "range",
      "id": "limit",
      "label": "Limit articles",
      "min": 2,
      "max": 50,
      "default": 48,
      "step": 1
    },
    {
      "type": "checkbox",
      "id": "show_article_count",
      "label": "Show count",
      "default": true
    },
    {
      "type": "checkbox",
      "id": "show_tags",
      "label": "Show tags",
      "default": true
    },
    {
      "type": "select",
      "id": "tags_btn_color",
      "label": "Tags button color",
      "default": "btn-outline-primary",
      "options": [
        { "group": "Solid", "value": "btn-primary", "label": "Primary" },
        { "group": "Solid", "value": "btn-secondary", "label": "Secondary" },
        { "group": "Solid", "value": "btn-white", "label": "White" },
        { "group": "Light", "value": "btn-light-primary", "label": "Primary" },
        { "group": "Light", "value": "btn-light-secondary", "label": "Secondary" },
        { "group": "Light", "value": "btn-light-white", "label": "White" },
        { "group": "Outline", "value": "btn-outline-primary", "label": "Primary" },
        { "group": "Outline", "value": "btn-outline-secondary", "label": "Secondary" },
        { "group": "Outline", "value": "btn-outline-white", "label": "White" }
      ]
    },
    {
      "type": "header",
      "content": "Article card"
    },
    {
      "type": "select",
      "id": "article_card_text_align",
      "label": "Text align",
      "default": "text-center",
      "options": [
        { "value": "text-start", "label": "Left" },
        { "value": "text-center", "label": "Center" }
      ]
    },
    {
      "type": "select",
      "id": "article_card_img_orientation",
      "label": "Image orientation",
      "default": "ratio-4x3",
      "options": [
        { "group": "Adapt", "value": "adapt", "label": "Adapt" },
        { "group": "Square", "value": "ratio-1x1", "label": "1x1" },
        { "group": "Horizontal", "value": "ratio-4x3", "label": "4x3" },
        { "group": "Horizontal", "value": "ratio-16x9", "label": "16x9" },
        { "group": "Horizontal", "value": "ratio-21x9", "label": "21x9" }
      ]
    },
    {
      "type": "select",
      "id": "article_card_img_border",
      "label": "Image border",
      "default": "img-thumbnail",
      "options": [
        { "value": "", "label": "None" },
        { "value": "rounded", "label": "Rounded" },
        { "value": "img-thumbnail", "label": "Thumbnail" }
      ]
    },
    {
      "type": "select",
      "id": "article_card_title_size",
      "label": "Title font-size",
      "default": "fs-xl",
      "options": [
        { "value": "fs-sm", "label": "sm" },
        { "value": "fs-md", "label": "md" },
        { "value": "fs-lg", "label": "lg" },
        { "value": "fs-xl", "label": "xl" },
        { "value": "fs-xxl", "label": "xxl" }
      ]
    },
    {
      "type": "checkbox",
      "id": "article_card_meta",
      "label": "Show author/date",
      "default": true
    },
    {
      "type": "checkbox",
      "id": "article_card_tags",
      "label": "Show tags",
      "default": true
    },
    {
      "type": "checkbox",
      "id": "article_card_excerpt",
      "label": "Show excerpt",
      "default": true
    },
    {
      "type": "header",
      "content": "Breakpoints",
      "info": "Adjust items per row based on the screen resolution"
    },
    {
      "type": "range",
      "id": "breakpoint_mobile",
      "label": "Mobile (<600px)",
      "min": 1,
      "max": 3,
      "step": 1,
      "default": 2
    },
    {
      "type": "range",
      "id": "breakpoint_tablet",
      "label": "Tablet (≥600px)",
      "min": 1,
      "max": 4,
      "step": 1,
      "default": 3
    },
    {
      "type": "range",
      "id": "breakpoint_desktop",
      "label": "Desktop (≥1200px)",
      "min": 1,
      "max": 6,
      "step": 1,
      "default": 4
    },
    {
      "type": "header",
      "content": "Spacing"
    },
    {
      "type": "range",
      "id": "pt",
      "label": "Top",
      "min": 0,
      "max": 20,
      "step": 1,
      "default": 10
    },
    {
      "type": "range",
      "id": "pb",
      "label": "Bottom",
      "min": 0,
      "max": 20,
      "step": 1,
      "default": 10
    }
  ],
  "templates": ["blog"],
  "presets": [
    {
      "name": "Blog"
    }
  ]
}
{% endschema %}

出典・ライセンス

License:
MIT

このコードは kondasoft 著作の MIT ライセンスソースです。 原本の著作権は kondasoft が保有します。日本語訳は ALSEL によるものです。

関連項目

📄 ページテンプレート初級

ページテンプレート

Shopify の汎用ページテンプレート。ページのタイトルと本文コンテンツを Shopify 管理画面から取得して表示する基本的な構造。

📁 liquid·MIT·5
📄 ページテンプレート初級

リダイレクト

ヘッドレステーマで Shopify ストアフロントへのリダイレクト機能を提供するセクション。管理画面に「リダイレクト」という名称で登場し、ページから別 URL への誘導を実装する基盤となる。

📁 shopify-headless-theme·MIT·7
📄 ページテンプレート初級

トップページの基本テンプレート

Shopify Liquid の最小限のテンプレート例。HTML に日付変数を埋め込み、商品ページへのリンクを配置する基本構造を示す。

📁 liquid·MIT·7
📄 ページテンプレート初級

固定ページのテンプレート

Shopify 管理画面で作成した固定ページ(利用規約、プライバシーポリシーなど)を表示するテンプレート。ページタイトルと本文コンテンツを描画する。

📁 mcliquid-theme·MIT·8
📄 ページテンプレート初級

ページの基本テンプレート

固定ページ(About など)の基本レイアウト。ページタイトルとコンテンツを HTML の article 要素でマークアップし、管理画面で編集したテキストを表示する。

📁 liquid·MIT·9
📄 ページテンプレート初級

固定ページのテンプレート

固定ページ(ポリシー、会社概要、利用規約など)の基本レイアウト。ページタイトルと本文を中央揃えで表示する。

📁 ks-bootshop·MIT·10