{%- comment -%} MIT License · (c) 2026 Lintel · https://lintelagency.com/resources/shopify-sections {%- endcomment -%} {%- comment -%} Video hero: a full-bleed, muted, looping Shopify-hosted background video (with an optional separate mobile video) under an overlay, with eyebrow, heading, text and up to two buttons (blocks) on top. Desktop and mobile poster images (each with its focal point) show first, and stay when there is no JavaScript, no video, or the visitor prefers reduced motion. A pause / play button is always shown while a video can play. The video file only loads when the section is on screen, and it pauses when scrolled away or when the tab is hidden. Depends on: snippets/lib-image.liquid, snippets/lib-button.liquid {%- endcomment -%} {%- liquid assign s = section.settings assign heading_tag = s.heading_tag | default: 'h2' assign eager = false if section.index <= 2 assign eager = true endif comment Which video plays where: one video for every device, or a desktop and a mobile one. endcomment assign desktop_device = 'all' if s.video_mobile != blank assign desktop_device = 'desktop' endif assign has_video = false if s.video != blank or s.video_mobile != blank assign has_video = true endif -%}
{%- render 'lib-image', image: s.image, image_mobile: s.image_mobile, class: 'lib-video-hero__img', sizes: '100vw', eager: eager, placeholder: 'hero-apparel-1' -%} {%- for device in (1..2) -%} {%- liquid if device == 1 assign video = s.video assign max_width = 1920 assign device_name = desktop_device assign media = '(min-width: 750px)' if desktop_device == 'all' assign media = 'all' endif else assign video = s.video_mobile assign max_width = 1080 assign device_name = 'mobile' assign media = '(max-width: 749px)' endif comment Shopify transcodes every upload into several MP4 sizes (and HLS); take the largest MP4 that is still no wider than the device needs. endcomment assign source_url = '' assign source_width = 0 if video != blank for source in video.sources if source.mime_type == 'video/mp4' and source.width <= max_width and source.width > source_width assign source_url = source.url assign source_width = source.width endif endfor if source_url == blank for source in video.sources if source.mime_type == 'video/mp4' assign source_url = source.url break endif endfor endif endif -%} {%- if source_url != blank -%} {%- endif -%} {%- endfor -%}
{%- if s.eyebrow != blank -%}

{{ s.eyebrow | escape }}

{%- endif -%} {%- if s.heading != blank -%} <{{ heading_tag }} class="lib-video-hero__heading lib-video-hero__heading--{{ s.heading_size }}"> {{- s.heading -}} {%- endif -%} {%- if s.text != blank -%}
{{ s.text }}
{%- endif -%} {%- if section.blocks.size > 0 -%}
{%- for block in section.blocks -%} {%- liquid assign arrow = true if forloop.index > 1 assign arrow = false endif -%} {%- render 'lib-button', label: block.settings.label, url: block.settings.url, style: block.settings.style, new_tab: block.settings.new_tab, arrow: arrow -%} {%- endfor -%}
{%- endif -%}
{%- if has_video -%} {%- endif -%}
{% stylesheet %} .lib-video-hero { display: block; background-color: var(--lib-bg); color: var(--lib-text); padding: var(--lib-pt-m) 0 var(--lib-pb-m); } .lib-video-hero--page { padding-inline: 1rem; } .lib-video-hero__frame { position: relative; display: grid; min-height: 480px; isolation: isolate; overflow: hidden; background: color-mix(in srgb, var(--lib-text) 12%, #1c1917); } .lib-video-hero--page .lib-video-hero__frame { max-width: 1200px; margin-inline: auto; border-radius: var(--lib-radius-frame); } /* Height: mobile first, then desktop. */ .lib-video-hero[data-height-m='small'] .lib-video-hero__frame { min-height: 360px; } .lib-video-hero[data-height-m='medium'] .lib-video-hero__frame { min-height: 480px; } .lib-video-hero[data-height-m='large'] .lib-video-hero__frame { min-height: 600px; } .lib-video-hero[data-height-m='full'] .lib-video-hero__frame { min-height: 100vh; min-height: 100svh; } @media (min-width: 750px) { .lib-video-hero { padding-top: var(--lib-pt); padding-bottom: var(--lib-pb); } .lib-video-hero[data-height='small'] .lib-video-hero__frame { min-height: 440px; } .lib-video-hero[data-height='medium'] .lib-video-hero__frame { min-height: 600px; } .lib-video-hero[data-height='large'] .lib-video-hero__frame { min-height: 760px; } .lib-video-hero[data-height='full'] .lib-video-hero__frame { min-height: 100vh; min-height: 100svh; } } /* Visibility */ @media (max-width: 749px) { .lib-video-hero[data-show='desktop'] { display: none; } .lib-video-hero__video[data-device='desktop'] { display: none; } } @media (min-width: 750px) { .lib-video-hero[data-show='mobile'] { display: none; } .lib-video-hero__video[data-device='mobile'] { display: none; } } /* Poster, video and overlay fill the frame; the video fades in over the poster once it plays. */ .lib-video-hero__media, .lib-video-hero__overlay { position: absolute; inset: 0; } .lib-video-hero__media { z-index: -2; overflow: hidden; border-radius: inherit; } .lib-video-hero__img, .lib-video-hero__video { position: absolute; inset: 0; display: block; width: 100%; height: 100%; object-fit: cover; } .lib-video-hero__img:is(svg) { fill: color-mix(in srgb, #fff 18%, transparent); background: #57534e; } .lib-video-hero__video { opacity: 0; transition: opacity 0.6s ease; } .lib-video-hero__video.is-ready { opacity: 1; } .lib-video-hero__overlay { z-index: -1; border-radius: inherit; background: var(--lib-overlay); opacity: var(--lib-overlay-o); pointer-events: none; } /* Content position: mobile uses data-pos-m (top / middle / bottom), desktop the 9-way data-pos. */ .lib-video-hero__content { position: relative; z-index: 1; display: flex; flex-direction: column; justify-content: flex-end; min-width: 0; padding: 2rem 1.25rem 5rem; } .lib-video-hero__content[data-pos-m='top'] { justify-content: flex-start; } .lib-video-hero__content[data-pos-m='middle'] { justify-content: center; } .lib-video-hero__content[data-pos-m='bottom'] { justify-content: flex-end; } .lib-video-hero__content[data-align-m='left'] { align-items: flex-start; } .lib-video-hero__content[data-align-m='center'] { align-items: center; } .lib-video-hero__content[data-align-m='right'] { align-items: flex-end; } @media (min-width: 750px) { .lib-video-hero__content { padding: clamp(2.5rem, 5vw, 4.5rem) clamp(2rem, 5vw, 4.5rem); } .lib-video-hero--full .lib-video-hero__content { padding-inline: max(clamp(2rem, 5vw, 4.5rem), calc((100% - 1200px) / 2 + 1rem)); } .lib-video-hero__content[data-pos^='top'] { justify-content: flex-start; } .lib-video-hero__content[data-pos^='middle'] { justify-content: center; } .lib-video-hero__content[data-pos^='bottom'] { justify-content: flex-end; } .lib-video-hero__content[data-pos$='left'] { align-items: flex-start; } .lib-video-hero__content[data-pos$='center'] { align-items: center; } .lib-video-hero__content[data-pos$='right'] { align-items: flex-end; } } /* Content box: transparent, or a solid card with its own colors. */ .lib-video-hero__box { display: flex; flex-direction: column; align-items: flex-start; width: 100%; max-width: var(--lib-content-w); text-align: left; } .lib-video-hero__box[data-box='solid'] { --lib-text: var(--lib-box-text); --lib-accent: var(--lib-box-text); --lib-accent-text: var(--lib-box); color: var(--lib-box-text); background: var(--lib-box); padding: clamp(1.5rem, 4vw, 2.75rem); border-radius: 4px; box-shadow: 0 24px 48px -28px rgb(0 0 0 / 0.45); } .lib-video-hero__box[data-align-m='center'] { align-items: center; text-align: center; } .lib-video-hero__box[data-align-m='right'] { align-items: flex-end; text-align: right; } @media (min-width: 750px) { .lib-video-hero__box { width: auto; } .lib-video-hero__box[data-align='left'] { align-items: flex-start; text-align: left; } .lib-video-hero__box[data-align='center'] { align-items: center; text-align: center; } .lib-video-hero__box[data-align='right'] { align-items: flex-end; text-align: right; } } .lib-video-hero__eyebrow { margin: 0 0 1rem; font-size: 0.8rem; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; } .lib-video-hero__heading { margin: 0; font-size: clamp(2.25rem, 5vw, 4rem); line-height: 1.05; letter-spacing: -0.025em; text-wrap: balance; overflow-wrap: anywhere; } .lib-video-hero__heading--small { font-size: clamp(1.75rem, 3vw, 2.5rem); } .lib-video-hero__heading--medium { font-size: clamp(2rem, 4vw, 3.25rem); } .lib-video-hero__heading--xlarge { font-size: clamp(2.75rem, 7vw, 5.5rem); } .lib-video-hero__text { margin-top: 1.125rem; font-size: 1.0625rem; line-height: 1.6; opacity: 0.9; } .lib-video-hero__text > :first-child { margin-top: 0; } .lib-video-hero__text > :last-child { margin-bottom: 0; } .lib-video-hero__text a { color: inherit; } .lib-video-hero__action { display: contents; } .lib-video-hero__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.75rem; } .lib-video-hero__box[data-align-m='center'] .lib-video-hero__actions { justify-content: center; } .lib-video-hero__box[data-align-m='right'] .lib-video-hero__actions { justify-content: flex-end; } @media (min-width: 750px) { .lib-video-hero__box[data-align='left'] .lib-video-hero__actions { justify-content: flex-start; } .lib-video-hero__box[data-align='center'] .lib-video-hero__actions { justify-content: center; } .lib-video-hero__box[data-align='right'] .lib-video-hero__actions { justify-content: flex-end; } } /* Pause / play: a 44px round button in the bottom corner, always above the overlay. */ .lib-video-hero__toggle { position: absolute; right: 1rem; bottom: 1rem; z-index: 2; display: grid; place-items: center; width: 2.75rem; height: 2.75rem; padding: 0; border: 0; border-radius: 50%; background: rgb(20 18 16 / 0.6); color: #fff; cursor: pointer; transition: background-color 0.2s ease; } .lib-video-hero__toggle[hidden] { display: none; } .lib-video-hero__toggle:hover { background: rgb(20 18 16 / 0.8); } .lib-video-hero__toggle:focus-visible { outline: 2px solid #fff; outline-offset: 3px; box-shadow: 0 0 0 5px rgb(20 18 16 / 0.7); } .lib-video-hero__toggle[data-state='playing'] .lib-video-hero__icon--play, .lib-video-hero__toggle[data-state='paused'] .lib-video-hero__icon--pause { display: none; } @media (min-width: 750px) { .lib-video-hero__toggle { right: 1.5rem; bottom: 1.5rem; } } /* Motion: the copy rises once on load. */ .lib-video-hero[data-animate] .lib-video-hero__box > * { animation: lib-video-hero-rise 0.8s cubic-bezier(0.2, 0.7, 0.2, 1) both; } .lib-video-hero[data-animate] .lib-video-hero__box > :nth-child(2) { animation-delay: 0.08s; } .lib-video-hero[data-animate] .lib-video-hero__box > :nth-child(3) { animation-delay: 0.16s; } .lib-video-hero[data-animate] .lib-video-hero__box > :nth-child(n + 4) { animation-delay: 0.24s; } @keyframes lib-video-hero-rise { from { opacity: 0; transform: translateY(14px); } } @media (prefers-reduced-motion: reduce) { .lib-video-hero[data-animate] .lib-video-hero__box > * { animation: none; } .lib-video-hero__video { transition: none; } } {% endstylesheet %} {% javascript %} if (!customElements.get('lib-video-hero')) { customElements.define( 'lib-video-hero', class extends HTMLElement { connectedCallback() { this.videos = [...this.querySelectorAll('video[data-media]')]; this.button = this.querySelector('.lib-video-hero__toggle'); if (!this.videos.length || !this.button) return; this.queries = this.videos.map((video) => window.matchMedia(video.dataset.media)); // Visitors who ask for reduced motion start paused; they can still press play. this.userPaused = window.matchMedia('(prefers-reduced-motion: reduce)').matches; this.visible = false; this.cleanup = []; const listen = (target, type, fn) => { target.addEventListener(type, fn); this.cleanup.push(() => target.removeEventListener(type, fn)); }; const update = () => this.update(); listen(this.button, 'click', () => { this.userPaused = !this.userPaused; this.update(); }); this.queries.forEach((query) => listen(query, 'change', update)); listen(document, 'visibilitychange', update); this.videos.forEach((video) => listen(video, 'playing', () => video.classList.add('is-ready'))); this.observer = new IntersectionObserver( ([entry]) => { this.visible = entry.isIntersecting; this.update(); }, {rootMargin: '200px 0px'}, ); this.observer.observe(this); this.button.hidden = false; this.update(); } disconnectedCallback() { this.observer?.disconnect(); (this.cleanup || []).forEach((fn) => fn()); this.cleanup = []; } update() { const active = this.videos.find((video, i) => this.queries[i].matches); this.videos.forEach((video) => { if (video !== active) video.pause(); }); const shouldPlay = Boolean(active) && this.visible && !this.userPaused && !document.hidden; if (active && shouldPlay) { // The file is only requested the first time this video should play. const source = active.querySelector('source[data-src]'); if (source) { source.src = source.dataset.src; source.removeAttribute('data-src'); active.load(); } const playing = active.play(); if (playing) { playing.catch(() => { // Autoplay refused (data saver, browser policy): show the play button instead. this.userPaused = true; this.setButton(false); }); } } else if (active) { active.pause(); } this.button.hidden = !active; this.setButton(!this.userPaused); } setButton(playing) { this.button.dataset.state = playing ? 'playing' : 'paused'; this.button.setAttribute('aria-label', playing ? this.button.dataset.pauseLabel : this.button.dataset.playLabel); } }, ); } {% endjavascript %} {% schema %} { "name": "Lib · Video hero", "tag": "section", "class": "lib-section", "settings": [ { "type": "header", "content": "Video" }, { "type": "video", "id": "video", "label": "Desktop video", "info": "Upload to Shopify. Plays muted and looped; keep it short (10–30 s) and without important text." }, { "type": "video", "id": "video_mobile", "label": "Mobile video", "info": "Optional. Plays below 750px; a portrait video works best. Without it the desktop video plays everywhere." }, { "type": "image_picker", "id": "image", "label": "Desktop poster image", "info": "Shows while the video loads, and instead of it when motion is reduced or JavaScript is off." }, { "type": "image_picker", "id": "image_mobile", "label": "Mobile poster image", "info": "Optional. Shown below 750px." }, { "type": "text", "id": "pause_label", "label": "Pause button label", "info": "Read by screen readers.", "default": "Pause background video" }, { "type": "text", "id": "play_label", "label": "Play button label", "info": "Read by screen readers.", "default": "Play background video" }, { "type": "color", "id": "overlay_color", "label": "Overlay color", "default": "#1C1917" }, { "type": "range", "id": "overlay_opacity", "label": "Overlay opacity", "min": 0, "max": 90, "step": 5, "unit": "%", "default": 35 }, { "type": "header", "content": "Content" }, { "type": "text", "id": "eyebrow", "label": "Eyebrow", "default": "Made in our studio" }, { "type": "inline_richtext", "id": "heading", "label": "Heading", "default": "Shaped by hand, fired with care" }, { "type": "select", "id": "heading_tag", "label": "Heading tag", "info": "Use H1 only when this is the page's main heading.", "options": [ { "value": "h1", "label": "H1" }, { "value": "h2", "label": "H2" }, { "value": "h3", "label": "H3" }, { "value": "p", "label": "Paragraph" } ], "default": "h2" }, { "type": "select", "id": "heading_size", "label": "Heading size", "options": [ { "value": "small", "label": "Small" }, { "value": "medium", "label": "Medium" }, { "value": "large", "label": "Large" }, { "value": "xlarge", "label": "Extra large" } ], "default": "large" }, { "type": "richtext", "id": "text", "label": "Text", "default": "

Small-batch stoneware for everyday tables, glazed in earthy tones and made to last.

" }, { "type": "header", "content": "Layout" }, { "type": "select", "id": "height", "label": "Height on desktop", "options": [ { "value": "small", "label": "Small" }, { "value": "medium", "label": "Medium" }, { "value": "large", "label": "Large" }, { "value": "full", "label": "Full screen" } ], "default": "large" }, { "type": "select", "id": "height_mobile", "label": "Height on mobile", "options": [ { "value": "small", "label": "Small" }, { "value": "medium", "label": "Medium" }, { "value": "large", "label": "Large" }, { "value": "full", "label": "Full screen" } ], "default": "large" }, { "type": "select", "id": "section_width", "label": "Width", "options": [ { "value": "page", "label": "Page width" }, { "value": "full", "label": "Full width" } ], "default": "full" }, { "type": "range", "id": "corner_radius", "label": "Corner radius", "min": 0, "max": 40, "step": 2, "unit": "px", "default": 12, "visible_if": "{{ section.settings.section_width == 'page' }}" }, { "type": "select", "id": "content_position", "label": "Content position on desktop", "info": "Text aligns to the same side: left, center or right.", "options": [ { "value": "top-left", "label": "Top left" }, { "value": "top-center", "label": "Top center" }, { "value": "top-right", "label": "Top right" }, { "value": "middle-left", "label": "Middle left" }, { "value": "middle-center", "label": "Middle center" }, { "value": "middle-right", "label": "Middle right" }, { "value": "bottom-left", "label": "Bottom left" }, { "value": "bottom-center", "label": "Bottom center" }, { "value": "bottom-right", "label": "Bottom right" } ], "default": "middle-left" }, { "type": "select", "id": "content_position_mobile", "label": "Content position on mobile", "options": [ { "value": "top", "label": "Top" }, { "value": "middle", "label": "Middle" }, { "value": "bottom", "label": "Bottom" } ], "default": "bottom" }, { "type": "select", "id": "text_alignment_mobile", "label": "Text alignment on mobile", "options": [ { "value": "left", "label": "Left" }, { "value": "center", "label": "Center" }, { "value": "right", "label": "Right" } ], "default": "left" }, { "type": "range", "id": "content_width", "label": "Content max width", "min": 320, "max": 960, "step": 20, "unit": "px", "default": 620 }, { "type": "select", "id": "content_box", "label": "Content box", "options": [ { "value": "none", "label": "None (text on video)" }, { "value": "solid", "label": "Solid card" } ], "default": "none" }, { "type": "header", "content": "Colors" }, { "type": "color", "id": "color_bg", "label": "Background", "info": "Shows around the hero when it has padding or page width.", "default": "#F5EFE6" }, { "type": "color", "id": "color_text", "label": "Text", "default": "#FFFFFF" }, { "type": "color", "id": "color_accent", "label": "Solid button", "default": "#FFFFFF" }, { "type": "color", "id": "color_accent_text", "label": "Text on solid button", "default": "#1C1917" }, { "type": "color", "id": "color_box", "label": "Content box", "default": "#F5EFE6", "visible_if": "{{ section.settings.content_box == 'solid' }}" }, { "type": "color", "id": "color_box_text", "label": "Text in content box", "info": "Also used for the solid button inside the box.", "default": "#2A211B", "visible_if": "{{ section.settings.content_box == 'solid' }}" }, { "type": "header", "content": "Spacing and visibility" }, { "type": "range", "id": "padding_top", "label": "Top padding on desktop", "min": 0, "max": 200, "step": 4, "unit": "px", "default": 0 }, { "type": "range", "id": "padding_bottom", "label": "Bottom padding on desktop", "min": 0, "max": 200, "step": 4, "unit": "px", "default": 0 }, { "type": "range", "id": "padding_top_mobile", "label": "Top padding on mobile", "min": 0, "max": 160, "step": 4, "unit": "px", "default": 0 }, { "type": "range", "id": "padding_bottom_mobile", "label": "Bottom padding on mobile", "min": 0, "max": 160, "step": 4, "unit": "px", "default": 0 }, { "type": "select", "id": "show_on", "label": "Show on", "options": [ { "value": "all", "label": "All devices" }, { "value": "desktop", "label": "Desktop only" }, { "value": "mobile", "label": "Mobile only" } ], "default": "all" }, { "type": "text", "id": "anchor_id", "label": "Anchor ID", "info": "Optional. Link to this section with #your-id." }, { "type": "header", "content": "Motion" }, { "type": "checkbox", "id": "animate", "label": "Animate text on load", "info": "Never when reduced motion is on.", "default": true } ], "blocks": [ { "type": "button", "name": "Button", "limit": 2, "settings": [ { "type": "text", "id": "label", "label": "Label", "default": "Shop new pieces" }, { "type": "url", "id": "url", "label": "Link" }, { "type": "select", "id": "style", "label": "Style", "options": [ { "value": "primary", "label": "Solid" }, { "value": "outline", "label": "Outline" }, { "value": "text", "label": "Text link" } ], "default": "primary" }, { "type": "checkbox", "id": "new_tab", "label": "Open link in a new tab", "default": false } ] } ], "presets": [ { "name": "Lib · Video hero", "blocks": [ { "type": "button", "settings": { "label": "Shop new pieces", "style": "primary" } }, { "type": "button", "settings": { "label": "Our story", "style": "outline" } } ] } ] } {% endschema %}