Skip to Content
🎉 探索 Shopify 的无限可能 结构化知识 + 实战案例,持续更新中...
Liquid 开发自定义分区开发

自定义分区开发

自定义分区是 Shopify 主题开发的核心功能,允许商家通过主题编辑器灵活配置页面内容。本指南将详细介绍如何开发高质量的自定义分区。

分区基础结构

1. 基本分区模板

<!-- sections/hero-banner.liquid --> <section class="hero-banner hero-banner--{{ section.id }}" data-section-id="{{ section.id }}"> <div class="hero-banner__container"> {% if section.settings.image %} <div class="hero-banner__image"> {% assign image_alt = section.settings.image.alt | default: section.settings.heading %} <img src="{{ section.settings.image | img_url: '1920x800' }}" alt="{{ image_alt }}" class="hero-banner__img" loading="lazy"> </div> {% endif %} <div class="hero-banner__content"> {% if section.settings.heading %} <h1 class="hero-banner__heading">{{ section.settings.heading }}</h1> {% endif %} {% if section.settings.subheading %} <p class="hero-banner__subheading">{{ section.settings.subheading }}</p> {% endif %} {% if section.settings.button_text and section.settings.button_url %} <a href="{{ section.settings.button_url }}" class="btn btn--{{ section.settings.button_style }}"> {{ section.settings.button_text }} </a> {% endif %} </div> </div> </section> <style> .hero-banner--{{ section.id }} { background-color: {{ section.settings.background_color }}; color: {{ section.settings.text_color }}; text-align: {{ section.settings.text_alignment }}; padding: {{ section.settings.padding_top }}px 0 {{ section.settings.padding_bottom }}px; } </style> {% schema %} { "name": "英雄横幅", "settings": [ { "type": "image_picker", "id": "image", "label": "背景图片" }, { "type": "text", "id": "heading", "label": "标题", "default": "欢迎来到我们的商店" }, { "type": "textarea", "id": "subheading", "label": "副标题", "default": "发现我们精选的优质产品" }, { "type": "text", "id": "button_text", "label": "按钮文字", "default": "立即购买" }, { "type": "url", "id": "button_url", "label": "按钮链接" }, { "type": "select", "id": "button_style", "label": "按钮样式", "options": [ { "value": "primary", "label": "主要" }, { "value": "secondary", "label": "次要" }, { "value": "outline", "label": "轮廓" } ], "default": "primary" }, { "type": "color", "id": "background_color", "label": "背景颜色", "default": "#ffffff" }, { "type": "color", "id": "text_color", "label": "文字颜色", "default": "#000000" }, { "type": "select", "id": "text_alignment", "label": "文字对齐", "options": [ { "value": "left", "label": "左对齐" }, { "value": "center", "label": "居中" }, { "value": "right", "label": "右对齐" } ], "default": "center" }, { "type": "range", "id": "padding_top", "label": "顶部间距", "min": 0, "max": 100, "step": 5, "unit": "px", "default": 50 }, { "type": "range", "id": "padding_bottom", "label": "底部间距", "min": 0, "max": 100, "step": 5, "unit": "px", "default": 50 } ], "presets": [ { "name": "英雄横幅", "category": "营销" } ] } {% endschema %}

2. 产品展示分区

<!-- sections/featured-products.liquid --> <section class="featured-products" data-section-id="{{ section.id }}"> <div class="container"> {% if section.settings.heading %} <header class="section-header"> <h2 class="section-title">{{ section.settings.heading }}</h2> {% if section.settings.description %} <p class="section-description">{{ section.settings.description }}</p> {% endif %} </header> {% endif %} {% assign collection = collections[section.settings.collection] %} {% if collection.products.size > 0 %} <div class="products-grid products-grid--{{ section.settings.columns_desktop }}"> {% for product in collection.products limit: section.settings.products_to_show %} <div class="product-item"> {% render 'product-card', product: product, show_vendor: section.settings.show_vendor, show_reviews: section.settings.show_reviews, image_ratio: section.settings.image_ratio %} </div> {% endfor %} </div> {% if section.settings.show_view_all and collection.products.size > section.settings.products_to_show %} <div class="section-footer"> <a href="{{ collection.url }}" class="btn btn--outline"> 查看全部 {{ collection.title }} </a> </div> {% endif %} {% else %} <div class="section-empty"> <p>请在主题编辑器中选择一个包含产品的集合。</p> </div> {% endif %} </div> </section> <style> .featured-products { padding: {{ section.settings.padding_top }}px 0 {{ section.settings.padding_bottom }}px; background-color: {{ section.settings.background_color }}; } .products-grid { display: grid; gap: 2rem; grid-template-columns: repeat({{ section.settings.columns_mobile }}, 1fr); } @media (min-width: 768px) { .products-grid { grid-template-columns: repeat({{ section.settings.columns_tablet }}, 1fr); } } @media (min-width: 1024px) { .products-grid { grid-template-columns: repeat({{ section.settings.columns_desktop }}, 1fr); } } </style> {% schema %} { "name": "精选产品", "settings": [ { "type": "text", "id": "heading", "label": "标题", "default": "精选产品" }, { "type": "richtext", "id": "description", "label": "描述" }, { "type": "collection", "id": "collection", "label": "产品集合" }, { "type": "range", "id": "products_to_show", "label": "显示产品数量", "min": 2, "max": 12, "step": 1, "default": 8 }, { "type": "range", "id": "columns_desktop", "label": "桌面端列数", "min": 2, "max": 6, "step": 1, "default": 4 }, { "type": "range", "id": "columns_tablet", "label": "平板端列数", "min": 1, "max": 4, "step": 1, "default": 3 }, { "type": "range", "id": "columns_mobile", "label": "移动端列数", "min": 1, "max": 2, "step": 1, "default": 2 }, { "type": "checkbox", "id": "show_vendor", "label": "显示品牌", "default": false }, { "type": "checkbox", "id": "show_reviews", "label": "显示评价", "default": true }, { "type": "checkbox", "id": "show_view_all", "label": "显示查看全部按钮", "default": true }, { "type": "select", "id": "image_ratio", "label": "图片比例", "options": [ { "value": "square", "label": "正方形" }, { "value": "portrait", "label": "竖向" }, { "value": "landscape", "label": "横向" } ], "default": "square" }, { "type": "color", "id": "background_color", "label": "背景颜色", "default": "#ffffff" }, { "type": "range", "id": "padding_top", "label": "顶部间距", "min": 0, "max": 100, "step": 5, "unit": "px", "default": 50 }, { "type": "range", "id": "padding_bottom", "label": "底部间距", "min": 0, "max": 100, "step": 5, "unit": "px", "default": 50 } ], "presets": [ { "name": "精选产品", "category": "产品" } ] } {% endschema %}

高级分区功能

1. 带有动态内容块的分区

<!-- sections/testimonials.liquid --> <section class="testimonials" data-section-id="{{ section.id }}"> <div class="container"> {% if section.settings.heading %} <header class="section-header"> <h2 class="section-title">{{ section.settings.heading }}</h2> </header> {% endif %} {% if section.blocks.size > 0 %} <div class="testimonials-grid"> {% for block in section.blocks %} <div class="testimonial-item" {{ block.shopify_attributes }}> {% if block.settings.avatar %} <div class="testimonial-avatar"> <img src="{{ block.settings.avatar | img_url: '80x80' }}" alt="{{ block.settings.customer_name }}" class="testimonial-avatar__img"> </div> {% endif %} <div class="testimonial-content"> {% if block.settings.review %} <blockquote class="testimonial-quote"> "{{ block.settings.review }}" </blockquote> {% endif %} <cite class="testimonial-author"> {% if block.settings.customer_name %} <strong class="testimonial-name">{{ block.settings.customer_name }}</strong> {% endif %} {% if block.settings.customer_title %} <span class="testimonial-title">{{ block.settings.customer_title }}</span> {% endif %} </cite> {% if block.settings.rating > 0 %} <div class="testimonial-rating"> {% for i in (1..5) %} <span class="star {% if i <= block.settings.rating %}star--filled{% endif %}">★</span> {% endfor %} </div> {% endif %} </div> </div> {% endfor %} </div> {% else %} <div class="section-empty"> <p>请添加客户评价内容。</p> </div> {% endif %} </div> </section> <style> .testimonials { padding: {{ section.settings.padding_top }}px 0 {{ section.settings.padding_bottom }}px; background-color: {{ section.settings.background_color }}; } .testimonials-grid { display: grid; gap: 2rem; grid-template-columns: repeat({{ section.settings.columns_mobile }}, 1fr); } @media (min-width: 768px) { .testimonials-grid { grid-template-columns: repeat({{ section.settings.columns_tablet }}, 1fr); } } @media (min-width: 1024px) { .testimonials-grid { grid-template-columns: repeat({{ section.settings.columns_desktop }}, 1fr); } } </style> {% schema %} { "name": "客户评价", "settings": [ { "type": "text", "id": "heading", "label": "标题", "default": "客户评价" }, { "type": "range", "id": "columns_desktop", "label": "桌面端列数", "min": 1, "max": 4, "step": 1, "default": 3 }, { "type": "range", "id": "columns_tablet", "label": "平板端列数", "min": 1, "max": 3, "step": 1, "default": 2 }, { "type": "range", "id": "columns_mobile", "label": "移动端列数", "min": 1, "max": 2, "step": 1, "default": 1 }, { "type": "color", "id": "background_color", "label": "背景颜色", "default": "#f8f8f8" }, { "type": "range", "id": "padding_top", "label": "顶部间距", "min": 0, "max": 100, "step": 5, "unit": "px", "default": 50 }, { "type": "range", "id": "padding_bottom", "label": "底部间距", "min": 0, "max": 100, "step": 5, "unit": "px", "default": 50 } ], "blocks": [ { "type": "testimonial", "name": "评价", "settings": [ { "type": "image_picker", "id": "avatar", "label": "客户头像" }, { "type": "text", "id": "customer_name", "label": "客户姓名" }, { "type": "text", "id": "customer_title", "label": "客户职位" }, { "type": "textarea", "id": "review", "label": "评价内容" }, { "type": "range", "id": "rating", "label": "评分", "min": 0, "max": 5, "step": 1, "default": 5 } ] } ], "presets": [ { "name": "客户评价", "blocks": [ { "type": "testimonial", "settings": { "customer_name": "张三", "review": "产品质量非常好,服务也很到位!", "rating": 5 } }, { "type": "testimonial", "settings": { "customer_name": "李四", "review": "物流很快,包装精美,会继续购买。", "rating": 5 } } ] } ], "max_blocks": 12 } {% endschema %}

2. 复杂的多媒体分区

<!-- sections/media-showcase.liquid --> <section class="media-showcase" data-section-id="{{ section.id }}"> <div class="container"> {% if section.settings.heading %} <header class="section-header"> <h2 class="section-title">{{ section.settings.heading }}</h2> {% if section.settings.description %} <p class="section-description">{{ section.settings.description }}</p> {% endif %} </header> {% endif %} {% if section.blocks.size > 0 %} <div class="media-grid media-grid--{{ section.settings.layout }}"> {% for block in section.blocks %} <div class="media-item media-item--{{ block.type }}" {{ block.shopify_attributes }}> {% case block.type %} {% when 'image' %} {% if block.settings.image %} <div class="media-image"> {% if block.settings.link %} <a href="{{ block.settings.link }}"> {% endif %} <img src="{{ block.settings.image | img_url: '800x600' }}" alt="{{ block.settings.image.alt | default: block.settings.heading }}" class="media-image__img" loading="lazy"> {% if block.settings.overlay_text %} <div class="media-overlay"> <div class="media-overlay__content"> {% if block.settings.heading %} <h3 class="media-overlay__heading">{{ block.settings.heading }}</h3> {% endif %} {% if block.settings.text %} <p class="media-overlay__text">{{ block.settings.text }}</p> {% endif %} </div> </div> {% endif %} {% if block.settings.link %} </a> {% endif %} </div> {% endif %} {% when 'video' %} <div class="media-video"> {% if block.settings.video_url %} {% assign video_id = block.settings.video_url | split: '/' | last %} {% if block.settings.video_url contains 'youtube' %} {% assign video_id = block.settings.video_url | split: 'v=' | last | split: '&' | first %} <iframe src="https://www.youtube.com/embed/{{ video_id }}" frameborder="0" allowfullscreen class="media-video__iframe"></iframe> {% elsif block.settings.video_url contains 'vimeo' %} <iframe src="https://player.vimeo.com/video/{{ video_id }}" frameborder="0" allowfullscreen class="media-video__iframe"></iframe> {% endif %} {% endif %} </div> {% when 'text' %} <div class="media-text"> {% if block.settings.heading %} <h3 class="media-text__heading">{{ block.settings.heading }}</h3> {% endif %} {% if block.settings.text %} <div class="media-text__content"> {{ block.settings.text }} </div> {% endif %} {% if block.settings.button_text and block.settings.button_url %} <a href="{{ block.settings.button_url }}" class="btn btn--{{ block.settings.button_style }}"> {{ block.settings.button_text }} </a> {% endif %} </div> {% endcase %} </div> {% endfor %} </div> {% endif %} </div> </section> <style> .media-showcase { padding: {{ section.settings.padding_top }}px 0 {{ section.settings.padding_bottom }}px; } .media-grid--masonry { columns: {{ section.settings.columns_mobile }}; column-gap: 2rem; } .media-grid--grid { display: grid; gap: 2rem; grid-template-columns: repeat({{ section.settings.columns_mobile }}, 1fr); } @media (min-width: 768px) { .media-grid--masonry { columns: {{ section.settings.columns_tablet }}; } .media-grid--grid { grid-template-columns: repeat({{ section.settings.columns_tablet }}, 1fr); } } @media (min-width: 1024px) { .media-grid--masonry { columns: {{ section.settings.columns_desktop }}; } .media-grid--grid { grid-template-columns: repeat({{ section.settings.columns_desktop }}, 1fr); } } </style> {% schema %} { "name": "多媒体展示", "settings": [ { "type": "text", "id": "heading", "label": "标题" }, { "type": "richtext", "id": "description", "label": "描述" }, { "type": "select", "id": "layout", "label": "布局样式", "options": [ { "value": "grid", "label": "网格" }, { "value": "masonry", "label": "瀑布流" } ], "default": "grid" }, { "type": "range", "id": "columns_desktop", "label": "桌面端列数", "min": 2, "max": 5, "step": 1, "default": 3 }, { "type": "range", "id": "columns_tablet", "label": "平板端列数", "min": 1, "max": 4, "step": 1, "default": 2 }, { "type": "range", "id": "columns_mobile", "label": "移动端列数", "min": 1, "max": 2, "step": 1, "default": 1 } ], "blocks": [ { "type": "image", "name": "图片", "settings": [ { "type": "image_picker", "id": "image", "label": "图片" }, { "type": "url", "id": "link", "label": "链接" }, { "type": "checkbox", "id": "overlay_text", "label": "显示覆盖文字", "default": false }, { "type": "text", "id": "heading", "label": "标题" }, { "type": "textarea", "id": "text", "label": "文字" } ] }, { "type": "video", "name": "视频", "settings": [ { "type": "url", "id": "video_url", "label": "视频链接", "info": "支持 YouTube 和 Vimeo" } ] }, { "type": "text", "name": "文字", "settings": [ { "type": "text", "id": "heading", "label": "标题" }, { "type": "richtext", "id": "text", "label": "内容" }, { "type": "text", "id": "button_text", "label": "按钮文字" }, { "type": "url", "id": "button_url", "label": "按钮链接" }, { "type": "select", "id": "button_style", "label": "按钮样式", "options": [ { "value": "primary", "label": "主要" }, { "value": "secondary", "label": "次要" } ] } ] } ], "presets": [ { "name": "多媒体展示" } ] } {% endschema %}

Schema 配置详解

1. 常用设置类型

{% schema %} { "name": "分区名称", "settings": [ // 文本输入 { "type": "text", "id": "heading", "label": "标题", "default": "默认标题", "placeholder": "输入标题..." }, // 多行文本 { "type": "textarea", "id": "description", "label": "描述", "default": "默认描述" }, // 富文本编辑器 { "type": "richtext", "id": "content", "label": "内容" }, // 数字范围 { "type": "range", "id": "columns", "label": "列数", "min": 1, "max": 6, "step": 1, "default": 3, "unit": "col" }, // 选择器 { "type": "select", "id": "style", "label": "样式", "options": [ { "value": "default", "label": "默认" }, { "value": "modern", "label": "现代" }, { "value": "classic", "label": "经典" } ], "default": "default" }, // 复选框 { "type": "checkbox", "id": "show_border", "label": "显示边框", "default": true }, // 颜色选择器 { "type": "color", "id": "background_color", "label": "背景颜色", "default": "#ffffff" }, // 图片选择器 { "type": "image_picker", "id": "background_image", "label": "背景图片" }, // 链接选择器 { "type": "url", "id": "button_link", "label": "按钮链接" }, // 产品选择器 { "type": "product", "id": "featured_product", "label": "特色产品" }, // 集合选择器 { "type": "collection", "id": "featured_collection", "label": "特色集合" }, // 博客选择器 { "type": "blog", "id": "featured_blog", "label": "特色博客" }, // 页面选择器 { "type": "page", "id": "info_page", "label": "信息页面" }, // 字体选择器 { "type": "font_picker", "id": "heading_font", "label": "标题字体", "default": "helvetica_n4" } ] } {% endschema %}

2. 分组设置

{% schema %} { "name": "高级分区", "settings": [ { "type": "header", "content": "内容设置" }, { "type": "text", "id": "heading", "label": "标题" }, { "type": "textarea", "id": "description", "label": "描述" }, { "type": "header", "content": "样式设置" }, { "type": "color", "id": "background_color", "label": "背景颜色" }, { "type": "color", "id": "text_color", "label": "文字颜色" }, { "type": "header", "content": "布局设置" }, { "type": "range", "id": "padding_top", "label": "顶部间距", "min": 0, "max": 100, "step": 5, "unit": "px" } ] } {% endschema %}

响应式和性能优化

1. 响应式图片处理

<!-- sections/responsive-gallery.liquid --> <section class="responsive-gallery"> {% for block in section.blocks %} {% if block.type == 'image' and block.settings.image %} <div class="gallery-item"> <picture class="gallery-picture"> <!-- 移动端图片 --> <source media="(max-width: 767px)" srcset="{{ block.settings.image | img_url: '400x300' }} 400w, {{ block.settings.image | img_url: '800x600' }} 800w" sizes="100vw"> <!-- 平板端图片 --> <source media="(max-width: 1023px)" srcset="{{ block.settings.image | img_url: '600x450' }} 600w, {{ block.settings.image | img_url: '1200x900' }} 1200w" sizes="50vw"> <!-- 桌面端图片 --> <source media="(min-width: 1024px)" srcset="{{ block.settings.image | img_url: '800x600' }} 800w, {{ block.settings.image | img_url: '1600x1200' }} 1600w" sizes="33vw"> <!-- 默认图片 --> <img src="{{ block.settings.image | img_url: '800x600' }}" alt="{{ block.settings.image.alt | escape }}" class="gallery-image" loading="lazy"> </picture> </div> {% endif %} {% endfor %} </section>

2. 延迟加载实现

<section class="lazy-section" data-lazy-section> <div class="lazy-placeholder" data-lazy-placeholder> <div class="loading-spinner">加载中...</div> </div> <div class="lazy-content" data-lazy-content style="display: none;"> <!-- 实际内容 --> {% for product in collections[section.settings.collection].products %} {% render 'product-card', product: product %} {% endfor %} </div> </section> <script> // 分区延迟加载 class LazySection { constructor(element) { this.section = element this.placeholder = element.querySelector('[data-lazy-placeholder]') this.content = element.querySelector('[data-lazy-content]') this.observer = null this.init() } init() { if ('IntersectionObserver' in window) { this.observer = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { this.loadContent() } }) }, { threshold: 0.1 }) this.observer.observe(this.section) } else { // 不支持 IntersectionObserver 的浏览器直接加载 this.loadContent() } } loadContent() { setTimeout(() => { this.placeholder.style.display = 'none' this.content.style.display = 'block' if (this.observer) { this.observer.disconnect() } }, 300) } } // 初始化延迟加载分区 document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('[data-lazy-section]').forEach(section => { new LazySection(section) }) }) </script>

分区最佳实践

1. 可访问性优化

<!-- 无障碍友好的分区 --> <section class="accessible-section" aria-labelledby="section-{{ section.id }}-heading" role="region"> {% if section.settings.heading %} <h2 id="section-{{ section.id }}-heading" class="section-title"> {{ section.settings.heading }} </h2> {% endif %} <div class="content-grid"> {% for block in section.blocks %} <article class="content-item" {{ block.shopify_attributes }}> {% if block.settings.image %} <img src="{{ block.settings.image | img_url: '400x300' }}" alt="{{ block.settings.image.alt | default: block.settings.heading | escape }}" role="img" aria-describedby="item-{{ block.id }}-description"> {% endif %} {% if block.settings.heading %} <h3 class="item-title">{{ block.settings.heading }}</h3> {% endif %} {% if block.settings.description %} <p id="item-{{ block.id }}-description" class="item-description"> {{ block.settings.description }} </p> {% endif %} {% if block.settings.link %} <a href="{{ block.settings.link }}" class="item-link" aria-label="了解更多关于 {{ block.settings.heading | escape }}"> 了解更多 </a> {% endif %} </article> {% endfor %} </div> </section>

2. SEO 优化

<!-- SEO 友好的分区 --> <section class="seo-optimized-section" itemscope itemtype="https://schema.org/ItemList"> {% if section.settings.heading %} <h2 class="section-title" itemprop="name">{{ section.settings.heading }}</h2> {% endif %} {% if section.settings.description %} <p class="section-description" itemprop="description"> {{ section.settings.description }} </p> {% endif %} <div class="items-grid"> {% for product in collections[section.settings.collection].products limit: section.settings.limit %} <article class="product-item" itemprop="itemListElement" itemscope itemtype="https://schema.org/Product"> <meta itemprop="position" content="{{ forloop.index }}"> <a href="{{ product.url }}" itemprop="url"> {% if product.featured_image %} <img src="{{ product.featured_image | img_url: '300x300' }}" alt="{{ product.featured_image.alt | default: product.title | escape }}" itemprop="image"> {% endif %} <h3 class="product-title" itemprop="name">{{ product.title }}</h3> <div class="product-price" itemprop="offers" itemscope itemtype="https://schema.org/Offer"> <span itemprop="price" content="{{ product.price | money_without_currency }}"> {{ product.price | money }} </span> <meta itemprop="priceCurrency" content="{{ shop.currency }}"> <meta itemprop="availability" content="{% if product.available %}InStock{% else %}OutOfStock{% endif %}"> </div> </a> </article> {% endfor %} </div> </section>

下一步学习

掌握自定义分区开发后,建议继续学习:

  1. 自定义代码片段 - 创建可复用组件
  2. 主题设置配置 - 全局主题配置
  3. 响应式设计实现 - 移动优先设计
  4. 电商功能实现 - 高级电商功能
  5. 第三方集成 - 外部服务集成

自定义分区是创建灵活、可配置主题的核心技能!

最后更新时间: