Introduction
Theme blocks are the foundation of Horizon’s architecture, enabling unprecedented flexibility and reusability. With 94 theme blocks in Horizon, this system represents the future of Shopify theme development.blocks/ directory that can be dynamically added to any section that accepts { "type": "@theme" }. They’re prefixed with an underscore (_).Core Concepts
What Makes a Theme Block?
A theme block is defined by three characteristics:Location
blocks/ directoryNaming
_heading.liquid, _content.liquidSchema
{% schema %} tag defining settings and configurationTheme Block vs Regular Block
- Theme Block
- Section-Specific Block
blocks/ directoryUsage: Can be added to ANY section with
{ "type": "@theme" }Reusability: Maximum - used across multiple sections
Horizon’s Theme Blocks Catalog
Horizon includes 94 theme blocks organized into categories:Content Blocks
Text & Headings
_heading.liquid- Customizable headings (h1-h6)_inline-text.liquid- Inline text elements_content.liquid- Nestable content groups_content-without-appearance.liquid- Content without styling
Dividers & Spacing
_divider.liquid- Visual dividers- Integrated spacing controls in all blocks
Media Blocks
Images
_image.liquid- Responsive images_media.liquid- Image/video media_media-without-appearance.liquid- Media without container
Advanced Media
_carousel-content.liquid- Carousel items_layered-slide.liquid- Layered slideshow slides_hotspot-product.liquid- Interactive hotspots
Product Blocks
Product Cards (8 blocks)
Product Cards (8 blocks)
_product-card.liquid- Complete product card_product-card-gallery.liquid- Product image gallery_product-card-group.liquid- Grouped product cards_product-details.liquid- Product information_featured-product.liquid- Featured product showcase_featured-product-gallery.liquid- Featured product images_featured-product-price.liquid- Product pricing_featured-product-information-carousel.liquid- Product info carousel
Product List Blocks (3 blocks)
Product List Blocks (3 blocks)
_product-list-content.liquid- Product list container_product-list-button.liquid- Product list actions
Collection Blocks
Collection Components (5 blocks)
Collection Components (5 blocks)
_collection-card.liquid- Collection card_collection-card-image.liquid- Collection image_collection-image.liquid- Collection banner image_collection-info.liquid- Collection information_collection-link.liquid- Collection navigation link_inline-collection-title.liquid- Inline collection title
Blog Blocks
Blog Components (8 blocks)
Blog Components (8 blocks)
_blog-post-card.liquid- Blog post card_blog-post-content.liquid- Post content_blog-post-description.liquid- Post excerpt_blog-post-featured-image.liquid- Post featured image_blog-post-image.liquid- Post inline image_blog-post-info-text.liquid- Post metadata_featured-blog-posts-card.liquid- Featured post card_featured-blog-posts-image.liquid- Featured post image_featured-blog-posts-title.liquid- Featured post title
Cart Blocks
_cart-products
_cart-summary
_cart-title
Navigation Blocks
Header Blocks (3 blocks)
Header Blocks (3 blocks)
_header-logo.liquid- Site logo with responsive sizing_header-menu.liquid- Main navigation menu_announcement.liquid- Announcement bar item
Accordion Blocks
_accordion-row
Layout Blocks
_card
_marquee
Block Architecture Patterns
1. Self-Contained Blocks
Simple blocks that render complete components:2. Wrapper Blocks with Delegation
Blocks that delegate rendering to snippets:"tag": null setting prevents Shopify from wrapping the block in a container, giving full control to the snippet.3. Nestable Container Blocks
Blocks that accept other blocks as children:Nesting and Composition
How Nesting Works
Theme blocks can be nested multiple levels deep:Rendering Flow
Section renders
_blocks.liquid section starts renderingcontent_for captures blocks
{% content_for 'blocks' %} captures all child blocksFirst-level blocks render
_content block starts renderingNested content_for
_content block calls {% content_for 'blocks' %} againNested blocks render
_image and button blocks render inside nested contentBubbles up
Practical Example
Static vs Dynamic Blocks
Static Blocks
Always present, cannot be removed:content_for 'block':
Dynamic Blocks
Can be added, removed, reordered by merchants:content_for 'blocks':
Advanced Features
Context Passing
Pass data to static blocks:Shopify Attributes
Preserve theme editor functionality:Conditional Settings with visible_if
Read-only Settings
Hide settings from merchants while preserving functionality:Creating Custom Theme Blocks
Basic Theme Block Template
Nestable Block Template
Best Practices
Keep blocks focused and single-purpose
Keep blocks focused and single-purpose
_heading.liquid, _image.liquid, _button.liquidBad:
_hero-with-everything.liquidAlways include {{ shopify_attributes }}
Always include {{ shopify_attributes }}
Use tag: null for custom rendering
Use tag: null for custom rendering
Leverage visible_if for better UX
Leverage visible_if for better UX
Use inheritance for color schemes
Use inheritance for color schemes
Common Patterns
Pattern: Block with Optional Link
Pattern: Block with Media Background
Pattern: Block with Responsive Settings
Debugging Theme Blocks
Inspecting Block Data
Visual Preview Mode Detection
Migration Guide
Converting Section Blocks to Theme Blocks
- Before (Section-specific)
- After (Theme blocks)
Performance Considerations
Minimize nesting depth
Minimize nesting depth
Use static blocks for fixed structure
Use static blocks for fixed structure
Lazy load images in blocks
Lazy load images in blocks
Scope CSS with {% stylesheet %}
Scope CSS with {% stylesheet %}