Skip to main content

Overview

Media blocks handle visual content including images and videos. Horizon provides three media block types:
  1. Image Block - Static images with aspect ratio controls
  2. Video Block - Uploaded or external videos with playback options
  3. Media Block - Unified block supporting both images and videos

Image Block

Displays responsive images with aspect ratio control and optional linking.

Settings

image
image_picker
Image to display
Optional URL to link the image

Size Settings

image_ratio
select
default:"adapt"
Image aspect ratio
  • adapt - Use original image ratio
  • portrait - 4:5 ratio (taller)
  • square - 1:1 ratio
  • landscape - 16:9 ratio (wider)
width
select
default:"fill"
Desktop width behavior
  • fit-content - Fit to image size
  • fill - Fill available space
  • custom - Custom percentage
custom_width
range
default:"100"
Custom width percentage (0-100%, visible when width is “custom”)
width_mobile
select
default:"fill"
Mobile width behavior
  • fit-content - Fit to image
  • fill - Fill container
  • custom - Custom percentage
custom_width_mobile
range
default:"100"
Mobile custom width (0-100%)
height
select
default:"fit"
Height behavior (visible when image_ratio is “adapt”)
  • fit - Fit to content
  • fill - Fill container height

Border Settings

border
select
default:"none"
Border style (none or solid)
border_width
range
default:"1"
Border thickness (0-100px)
border_opacity
range
default:"100"
Border opacity (0-100%)
border_radius
range
default:"0"
Corner radius (0-100px)

Padding Settings

Standard padding controls (0-100px) for all four sides.

Liquid Implementation

{% liquid
  assign block_settings = block.settings
  assign ratio = 1

  case block_settings.image_ratio
    when 'landscape'
      assign ratio = '16 / 9'
    when 'portrait'
      assign ratio = '4 / 5'
    when 'adapt'
      assign ratio = block_settings.image.aspect_ratio
  endcase

  if ratio == 0 or ratio == null
    assign ratio = 1
  endif
%}

{% capture image %}
  {%- if block_settings.image -%}
    {{
      block_settings.image
      | image_url: width: 3840
      | image_tag:
        widths: '240, 352, 832, 1200, 1600, 1920, 2560, 3840',
        sizes: 'auto',
        class: 'image-block__image border-style'
    }}
  {%- else -%}
    <div class="placeholder-image">
      {{ 'detailed-apparel-1' | placeholder_svg_tag }}
    </div>
  {%- endif -%}
{% endcapture %}

{% if block_settings.link == blank %}
  <div class="image-block" style="--ratio: {{ ratio }};" {{ block.shopify_attributes }}>
    {{ image }}
  </div>
{% else %}
  <a href="{{ block_settings.link }}" class="image-block">
    {{ image }}
  </a>
{% endif %}

CSS Classes

  • .image-block - Main container with flex display
  • .image-block__image - Image element with object-fit cover
  • .image-block--height-fill - Fills parent height
  • .placeholder-image - Placeholder when no image selected
  • .border-style - Border styling utilities

Video Block

Supports both uploaded videos and external video URLs (YouTube, Vimeo).

Settings

source
select
default:"uploaded"
Video source type
  • uploaded - Shopify-hosted video file
  • url - External video URL
video
video
Uploaded video file (visible when source is “uploaded”)
video_url
video_url
External video URL from YouTube or Vimeo (visible when source is “url”)
video_autoplay
checkbox
default:"false"
Autoplay video on page load
video_loop
checkbox
default:"true"
Loop video playback
cover_image
image_picker
Custom cover/poster image (visible for external videos when autoplay is off)
alt
text
Alternative text for accessibility (visible for external videos)

Size Settings

custom_width
range
default:"100"
Desktop width (0-100%)
custom_width_mobile
range
default:"100"
Mobile width (0-100%)
aspect_ratio
select
default:"auto"
Video aspect ratio (for external videos without cover image)
  • auto - Automatic
  • 9/16 - Portrait (9:16)
  • 1/1 - Square
  • 16/9 - Landscape (16:9)

Liquid Implementation

{% assign block_settings = block.settings %}

{% if block_settings.source == 'uploaded' %}
  {% render 'video',
    video: block_settings.video,
    video_loop: block_settings.video_loop,
    video_preview_image: block_settings.video.preview_image,
    section_id: section.id
  %}
{% else %}
  {% render 'video',
    video_from_url: true,
    video: block_settings.video_url.id,
    video_type: block_settings.video_url.type,
    video_alt: block_settings.alt,
    video_preview_image: block_settings.cover_image,
    section_id: section.id
  %}
{% endif %}

Media Block

Unified block that can display either an image or video based on settings.

Settings

media_type
select
default:"image"
Type of media to display
  • image - Static image
  • video - Video content
image
image_picker
Image to display (visible when media_type is “image”)
Link URL (visible when media_type is “image”)
video
video
Video file (visible when media_type is “video”)
video_loop
checkbox
default:"true"
Loop video playback (visible when media_type is “video”)
video_autoplay
checkbox
default:"false"
Autoplay video (visible when media_type is “video”)

Appearance Settings

inherit_color_scheme
checkbox
default:"true"
Inherit color scheme from parent section
color_scheme
color_scheme
default:"scheme-1"
Color scheme when not inheriting
border_radius
range
default:"0"
Corner radius (0-100px)

Padding Settings

Standard padding controls for all four sides (0-100px).

Liquid Implementation

{% render 'media', section_id: section.id %}
The media block uses the media snippet which handles the conditional rendering of images or videos.

Responsive Images

All image blocks use Shopify’s responsive image system:
{{
  image
  | image_url: width: 3840
  | image_tag:
    widths: '240, 352, 832, 1200, 1600, 1920, 2560, 3840',
    sizes: 'auto'
}}
This generates:
  • Multiple image sizes in srcset
  • Automatic size selection based on viewport
  • Lazy loading support
  • Optimal performance

Usage Examples

Hero Image

{
  "type": "image",
  "settings": {
    "image": "hero.jpg",
    "image_ratio": "landscape",
    "width": "fill",
    "link": "/collections/new"
  }
}

Looping Background Video

{
  "type": "video",
  "settings": {
    "source": "uploaded",
    "video_autoplay": true,
    "video_loop": true,
    "custom_width": 100
  }
}

YouTube Embed

{
  "type": "video",
  "settings": {
    "source": "url",
    "video_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "cover_image": "video-poster.jpg",
    "aspect_ratio": "16/9"
  }
}
{
  "blocks": [
    {
      "type": "image",
      "settings": {
        "image_ratio": "square",
        "width": "custom",
        "custom_width": 50,
        "border_radius": 8
      }
    },
    {
      "type": "image",
      "settings": {
        "image_ratio": "square",
        "width": "custom",
        "custom_width": 50,
        "border_radius": 8
      }
    }
  ]
}

Best Practices

Image Optimization

  1. Upload high-resolution images (at least 2000px wide)
  2. Use appropriate formats (WebP for photos, SVG for logos)
  3. Set alt text for accessibility
  4. Choose correct aspect ratio to avoid cropping

Video Performance

  1. Use autoplay sparingly - Can impact page performance
  2. Provide cover images - Faster initial load
  3. Consider file size - Compress videos before upload
  4. Use external URLs - YouTube/Vimeo for longer content

Responsive Design

  1. Set mobile widths - Different sizing for small screens
  2. Test aspect ratios - Ensure content looks good at all sizes
  3. Use adaptive ratios - When image proportions are important
  4. Add padding - Provide breathing room on mobile

Source Code Reference

  • Image Block: /source/blocks/image.liquid:1-331
  • Video Block: /source/blocks/video.liquid:1-255
  • Media Block: /source/blocks/_media.liquid:1-135

Build docs developers (and LLMs) love