ワンクリックで
shopify-section-patterns
Best practices for creating Shopify 2.0 sections with inline CSS and JavaScript
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Best practices for creating Shopify 2.0 sections with inline CSS and JavaScript
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Prisma ORM best practices for Shopify apps including multi-tenant data isolation, query optimization, transaction patterns, and migration strategies. Auto-invoked when working with database operations.
Build consistent UI using Polaris Web Components patterns for common page layouts like index pages, detail pages, forms, and empty states. Use this skill when creating new pages or refactoring existing UI components.
Common Shopify Admin GraphQL API patterns for product queries, metafield operations, webhooks, and bulk operations. Auto-invoked when working with Shopify API integration.
Polaris composition patterns and page templates for common Shopify app layouts. Provides index tables, settings pages, dashboards, and resource management patterns. Auto-invoked when building page layouts.
Core Polaris Web Components fundamentals including component library structure, design tokens, responsive patterns, and SSR compatibility. Auto-invoked when working with Polaris components.
Internationalization fundamentals for multi-language Shopify themes
| name | Shopify Section Patterns |
| description | Best practices for creating Shopify 2.0 sections with inline CSS and JavaScript |
A complete Shopify section consists of:
{% stylesheet %} tag (optional){% javascript %} tag (optional){% schema %} JSON configuration{%- comment -%}
Section: [Name]
Description: [Brief description]
Usage: Add via Theme Editor
{%- endcomment -%}
{%- liquid
assign heading = section.settings.heading | default: 'Default Heading'
assign bg_color = section.settings.bg_color
assign text_color = section.settings.text_color
-%}
<section
id="section-{{ section.id }}"
class="my-section"
data-section-id="{{ section.id }}"
>
<div class="container">
{%- if heading != blank -%}
<h2>{{ heading | escape }}</h2>
{%- endif -%}
{%- comment -%} Section content {%- endcomment -%}
</div>
</section>
{% stylesheet %}
#section-{{ section.id }} {
padding: {{ section.settings.padding_top }}px 0 {{ section.settings.padding_bottom }}px;
background-color: {{ bg_color }};
color: {{ text_color }};
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
@media (min-width: 768px) {
/* Tablet styles */
}
@media (min-width: 1024px) {
/* Desktop styles */
}
{% endstylesheet %}
{% javascript %}
(function() {
'use strict';
function initSection(sectionId) {
const section = document.querySelector('[data-section-id="' + sectionId + '"]');
if (!section) return;
// Your JavaScript here
}
// Initialize on page load
document.addEventListener('DOMContentLoaded', function() {
initSection('{{ section.id }}');
});
// Re-initialize when section reloads in theme editor
document.addEventListener('shopify:section:load', function(event) {
if (event.detail.sectionId === '{{ section.id }}') {
initSection('{{ section.id }}');
}
});
})();
{% endjavascript %}
{% schema %}
{
"name": "Section Name",
"tag": "section",
"class": "section-wrapper",
"settings": [
{
"type": "text",
"id": "heading",
"label": "Heading",
"default": "Default Heading"
},
{
"type": "color",
"id": "bg_color",
"label": "Background Color",
"default": "#ffffff"
},
{
"type": "color",
"id": "text_color",
"label": "Text Color",
"default": "#000000"
},
{
"type": "range",
"id": "padding_top",
"label": "Top Spacing",
"min": 0,
"max": 100,
"step": 4,
"unit": "px",
"default": 40
},
{
"type": "range",
"id": "padding_bottom",
"label": "Bottom Spacing",
"min": 0,
"max": 100,
"step": 4,
"unit": "px",
"default": 40
}
],
"presets": [
{
"name": "Section Name"
}
]
}
{% endschema %}
{% stylesheet %} When:{{ section.settings.color }}{% javascript %} When:{{ section.settings.enable_feature }}{{ section.id }} or other Liquid values{%- liquid
assign collection = section.settings.collection
assign products_count = section.settings.products_count
assign columns = section.settings.columns_desktop
-%}
<div class="product-grid">
{%- for product in collection.products limit: products_count -%}
<div class="product-item">
<a href="{{ product.url }}">
{%- if product.featured_image -%}
<img
src="{{ product.featured_image | image_url: width: 400 }}"
alt="{{ product.featured_image.alt | escape }}"
loading="lazy"
>
{%- endif -%}
<h3>{{ product.title | escape }}</h3>
<p>{{ product.price | money }}</p>
</a>
</div>
{%- endfor -%}
</div>
{% stylesheet %}
.product-grid {
display: grid;
gap: 1.5rem;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.product-grid {
grid-template-columns: repeat({{ columns }}, 1fr);
}
}
{% endstylesheet %}
{%- liquid
assign image = section.settings.image
assign heading = section.settings.heading
assign text = section.settings.text
assign button_label = section.settings.button_label
assign button_link = section.settings.button_link
-%}
<div class="hero-banner">
{%- if image -%}
<div class="hero-banner__image">
<img
src="{{ image | image_url: width: 1600 }}"
alt="{{ image.alt | escape }}"
>
</div>
{%- endif -%}
<div class="hero-banner__content">
{%- if heading != blank -%}
<h1>{{ heading | escape }}</h1>
{%- endif -%}
{%- if text != blank -%}
<p>{{ text }}</p>
{%- endif -%}
{%- if button_label != blank and button_link != blank -%}
<a href="{{ button_link }}" class="button">
{{ button_label | escape }}
</a>
{%- endif -%}
</div>
</div>
{% stylesheet %}
.hero-banner {
position: relative;
min-height: 500px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.hero-banner__image {
position: absolute;
inset: 0;
z-index: -1;
}
.hero-banner__image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.hero-banner__content {
padding: 2rem;
background: rgba(255, 255, 255, 0.9);
border-radius: 8px;
}
.button {
display: inline-block;
padding: 1rem 2rem;
background: #000;
color: #fff;
text-decoration: none;
border-radius: 4px;
margin-top: 1rem;
}
{% endstylesheet %}
<div class="testimonials">
{%- for block in section.blocks -%}
<div class="testimonial" {{ block.shopify_attributes }}>
{%- if block.settings.quote != blank -%}
<blockquote>
{{ block.settings.quote }}
</blockquote>
{%- endif -%}
{%- if block.settings.author != blank -%}
<cite>{{ block.settings.author | escape }}</cite>
{%- endif -%}
</div>
{%- endfor -%}
</div>
{% schema %}
{
"name": "Testimonials",
"blocks": [
{
"type": "testimonial",
"name": "Testimonial",
"settings": [
{
"type": "textarea",
"id": "quote",
"label": "Quote"
},
{
"type": "text",
"id": "author",
"label": "Author"
}
]
}
],
"presets": [
{
"name": "Testimonials",
"blocks": [
{
"type": "testimonial"
}
]
}
]
}
{% endschema %}
Handle theme editor events:
{% javascript %}
(function() {
'use strict';
function initSection(sectionId) {
const section = document.querySelector('[data-section-id="' + sectionId + '"]');
if (!section) return;
console.log('Section initialized:', sectionId);
}
function cleanupSection(sectionId) {
// Clean up event listeners, timers, etc.
console.log('Section cleaned up:', sectionId);
}
// Load event - section added or page loaded
document.addEventListener('shopify:section:load', function(event) {
initSection(event.detail.sectionId);
});
// Unload event - section removed
document.addEventListener('shopify:section:unload', function(event) {
cleanupSection(event.detail.sectionId);
});
// Select event - section selected in theme editor
document.addEventListener('shopify:section:select', function(event) {
console.log('Section selected:', event.detail.sectionId);
});
// Deselect event - section deselected in theme editor
document.addEventListener('shopify:section:deselect', function(event) {
console.log('Section deselected:', event.detail.sectionId);
});
// Block select event - block selected in theme editor
document.addEventListener('shopify:block:select', function(event) {
console.log('Block selected:', event.detail.blockId);
});
// Block deselect event - block deselected in theme editor
document.addEventListener('shopify:block:deselect', function(event) {
console.log('Block deselected:', event.detail.blockId);
});
// Initialize on page load
document.addEventListener('DOMContentLoaded', function() {
initSection('{{ section.id }}');
});
})();
{% endjavascript %}
<div id="section-{{ section.id }}" class="my-section">
<!-- Content -->
</div>
{% stylesheet %}
#section-{{ section.id }} {
/* Section-specific styles using Liquid variables */
background: {{ section.settings.bg_color }};
}
.my-section {
/* General styles without Liquid variables */
padding: 2rem 0;
}
{% endstylesheet %}
{%- liquid
assign heading = section.settings.heading | default: 'Default Heading'
assign columns = section.settings.columns | default: 3
assign show_prices = section.settings.show_prices | default: true
-%}
{%- if collection.products.size > 0 -%}
<!-- Show products -->
{%- else -%}
<p>No products available in this collection.</p>
{%- endif -%}
/* Mobile first - base styles */
.grid {
grid-template-columns: 1fr;
}
/* Tablet and up */
@media (min-width: 768px) {
.grid {
grid-template-columns: repeat(2, 1fr);
}
}
/* Desktop and up */
@media (min-width: 1024px) {
.grid {
grid-template-columns: repeat(3, 1fr);
}
}
<div
class="slider"
data-autoplay="{{ section.settings.autoplay }}"
data-speed="{{ section.settings.speed }}"
>
<!-- Slider content -->
</div>
{% javascript %}
const slider = document.querySelector('.slider');
const autoplay = slider.dataset.autoplay === 'true';
const speed = parseInt(slider.dataset.speed, 10);
{% endjavascript %}
<div class="card{% if product.available %} in-stock{% else %} sold-out{% endif %}">
<!-- Card content -->
</div>
{% stylesheet %}
.product-grid {
display: grid;
gap: 1.5rem;
grid-template-columns: repeat({{ section.settings.columns_mobile }}, 1fr);
}
@media (min-width: 1024px) {
.product-grid {
grid-template-columns: repeat({{ section.settings.columns_desktop }}, 1fr);
}
}
{% endstylesheet %}
{% javascript %}
function addToCart(button) {
button.classList.add('loading');
button.disabled = true;
// Add to cart logic...
button.classList.remove('loading');
button.disabled = false;
}
{% endjavascript %}
Create sections that are flexible, performant, and easy for merchants to customize through the theme editor.