This custom code is completely free to use, but please note it does not include 1-on-1 technical support. If you need a bespoke, done-for-you solution to customize your Shopify store, my team is here to help! Head to my channel homepage and use the link in the trailer to reach out.
{%- comment -%}
<!-- Designed by ONHOW Studio - Anas El Medlaoui -->
{%- endcomment -%}
{%- assign onhow_studio_video_src = '' -%}
{%- if section.settings.onhow_studio_video_file != blank -%}
{%- assign onhow_studio_video_src = section.settings.onhow_studio_video_file.sources[1].url | default: section.settings.onhow_studio_video_file.sources[0].url -%}
{%- elsif section.settings.onhow_studio_video_url != blank -%}
{%- assign onhow_studio_video_src = section.settings.onhow_studio_video_url -%}
{%- endif -%}
{%- assign onhow_studio_video_src_mobile = onhow_studio_video_src -%}
{%- if section.settings.onhow_studio_mobile_video_file != blank -%}
{%- assign onhow_studio_video_src_mobile = section.settings.onhow_studio_mobile_video_file.sources[1].url | default: section.settings.onhow_studio_mobile_video_file.sources[0].url -%}
{%- endif -%}
{%- assign onhow_studio_poster_src = section.settings.onhow_studio_poster_image | image_url: width: 1920 -%}
{%- assign onhow_studio_show_error = false -%}
{%- if onhow_studio_video_src == blank -%}
{%- assign onhow_studio_show_error = true -%}
{%- endif -%}
{%- assign onhow_studio_section_id = 'onhow-studio-scroll-video-' | append: section.id -%}
<style>
.onhow-studio-section-wrapper-{{ section.settings.onhow_studio_core_logic }} * { box-sizing: border-box; }
.onhow-studio-section-wrapper-{{ section.settings.onhow_studio_core_logic }} p,
.onhow-studio-section-wrapper-{{ section.settings.onhow_studio_core_logic }} h1,
.onhow-studio-section-wrapper-{{ section.settings.onhow_studio_core_logic }} h2,
.onhow-studio-section-wrapper-{{ section.settings.onhow_studio_core_logic }} ul { margin: 0; padding: 0; }
#{{ onhow_studio_section_id }} {
--onhow-studio-playback-speed: {{ section.settings.onhow_studio_playback_speed | default: 500 }};
--onhow-studio-scroll-multiplier: {{ section.settings.onhow_studio_scroll_multiplier | default: 1.0 }};
--onhow-studio-mobile-scroll-speed: {{ section.settings.onhow_studio_mobile_scroll_speed | default: 300 }};
--onhow-studio-sticky-offset: {{ section.settings.onhow_studio_sticky_offset | default: 0 }}px;
--onhow-studio-border-radius: {{ section.settings.onhow_studio_border_radius | default: 0 }}px;
--onhow-studio-padding-top: {{ section.settings.onhow_studio_padding_top | default: 36 }}px;
--onhow-studio-padding-bottom: {{ section.settings.onhow_studio_padding_bottom | default: 36 }}px;
--onhow-studio-overlay-color: {{ section.settings.onhow_studio_overlay_color | default: '#000000' }};
--onhow-studio-overlay-opacity: {{ section.settings.onhow_studio_overlay_opacity | default: 0 | divided_by: 100.0 }};
--onhow-studio-text-y: {{ section.settings.onhow_studio_text_vertical_position | default: 50 }}%;
}
#{{ onhow_studio_section_id }} .onhow-studio-scroll-video-wrapper {
padding-block-start: var(--onhow-studio-padding-top);
padding-block-end: var(--onhow-studio-padding-bottom);
{%- case section.settings.onhow_studio_container_width -%}
{%- when 'full-width' -%}
width: 100%;
max-width: none;
padding-inline: 0;
margin-inline: 0;
{%- when 'page-width' -%}
max-width: var(--page-width);
margin-inline: auto;
padding-inline: var(--page-gutter);
{%- when 'narrow' -%}
max-width: 1000px;
margin-inline: auto;
padding-inline: var(--page-gutter);
{%- endcase -%}
}
#{{ onhow_studio_section_id }} .onhow-studio-scroll-video-container {
position: sticky;
top: var(--onhow-studio-sticky-offset);
width: 100%;
z-index: 1;
}
#{{ onhow_studio_section_id }} .onhow-studio-scroll-video-element {
width: 100%;
height: auto;
display: block;
border-radius: var(--onhow-studio-border-radius);
{%- case section.settings.onhow_studio_shadow -%}
{%- when 'soft' -%}
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
{%- when 'strong' -%}
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
{%- else -%}
box-shadow: none;
{%- endcase -%}
}
#{{ onhow_studio_section_id }} .onhow-studio-scroll-video-spacer {
width: 100%;
height: 0;
}
#{{ onhow_studio_section_id }} .onhow-studio-scroll-video-error {
background-color: rgb(var(--color-background));
border: 1px solid rgb(var(--color-border));
padding: 2rem;
text-align: center;
border-radius: var(--onhow-studio-border-radius);
color: rgb(var(--color-foreground));
}
#{{ onhow_studio_section_id }} .onhow-studio-scroll-video-loading {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgb(var(--color-background));
border-radius: var(--onhow-studio-border-radius);
z-index: 2;
}
#{{ onhow_studio_section_id }} .onhow-studio-loading-spinner {
width: 40px;
height: 40px;
border: 3px solid rgba(var(--color-foreground-rgb), 0.1);
border-top-color: rgb(var(--color-foreground));
border-radius: 50%;
animation: onhow-studio-spin 0.8s linear infinite;
}
@keyframes onhow-studio-spin {
to { transform: rotate(360deg); }
}
#{{ onhow_studio_section_id }} .onhow-studio-content-above,
#{{ onhow_studio_section_id }} .onhow-studio-content-below {
text-align: center;
margin-block: 2rem;
}
#{{ onhow_studio_section_id }} .onhow-studio-content-overlay {
position: absolute;
left: 0;
right: 0;
top: var(--onhow-studio-text-y, 50%);
transform: translateY(-50%);
z-index: 2;
display: flex;
flex-direction: column;
align-items: center;
pointer-events: none;
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.6);
color: #fff;
padding: 2rem;
}
#{{ onhow_studio_section_id }} .onhow-studio-heading {
margin: 0;
color: inherit;
}
#{{ onhow_studio_section_id }} .onhow-studio-description {
margin-block-start: 1rem;
color: inherit;
}
#{{ onhow_studio_section_id }} .onhow-studio-subheading {
margin-block-start: 1rem;
color: inherit;
}
#{{ onhow_studio_section_id }} .onhow-studio-video-wrapper {
position: relative;
}
{%- if section.settings.onhow_studio_text_position == 'overlay' -%}
#{{ onhow_studio_section_id }} .onhow-studio-scroll-video-container::before {
content: '';
position: absolute;
inset: 0;
z-index: 1;
background: var(--onhow-studio-overlay-color);
opacity: var(--onhow-studio-overlay-opacity);
border-radius: var(--onhow-studio-border-radius);
pointer-events: none;
}
{%- endif -%}
#{{ onhow_studio_section_id }} .onhow-studio-scroll-video-mobile {
display: none;
}
@media (max-width: 749px) {
{%- if section.settings.onhow_studio_mobile_video_file != blank and section.settings.onhow_studio_mobile_behavior != 'hide' -%}
#{{ onhow_studio_section_id }} .onhow-studio-scroll-video-desktop { display: none; }
#{{ onhow_studio_section_id }} .onhow-studio-scroll-video-mobile { display: block; }
{%- endif -%}
}
#{{ onhow_studio_section_id }} .onhow-studio-static-video {
width: 100%;
border-radius: var(--onhow-studio-border-radius);
}
@media (max-width: 749px) {
{%- if section.settings.onhow_studio_mobile_behavior == 'hide' -%}
#{{ onhow_studio_section_id }} { display: none; }
{%- endif -%}
}
@media (prefers-reduced-motion: reduce) {
#{{ onhow_studio_section_id }} .onhow-studio-scroll-video-spacer { height: 0 !important; }
#{{ onhow_studio_section_id }} .onhow-studio-scroll-video-container { position: relative !important; }
}
</style>
<div id="{{ onhow_studio_section_id }}" class="onhow-studio-section-wrapper-{{ section.settings.onhow_studio_core_logic }}" style="--onhow-studio-bg: {{ section.settings.onhow_studio_bg_color }}; --onhow-studio-text: {{ section.settings.onhow_studio_text_color }};">
<div class="onhow-studio-scroll-video-wrapper">
{%- if onhow_studio_show_error -%}
<div class="onhow-studio-scroll-video-error">
<p>No video source configured. Please add a video in the section settings.</p>
</div>
{%- else -%}
{%- if section.settings.onhow_studio_heading != blank and section.settings.onhow_studio_text_position == 'above' -%}
<div class="onhow-studio-content-above">
<{{ section.settings.onhow_studio_heading_size }} class="onhow-studio-heading">{{ section.settings.onhow_studio_heading }}</{{ section.settings.onhow_studio_heading_size }}>
{%- if section.settings.onhow_studio_description != blank -%}
<div class="onhow-studio-description">{{ section.settings.onhow_studio_description }}</div>
{%- endif -%}
{%- if section.settings.onhow_studio_subheading != blank -%}
<div class="onhow-studio-subheading">{{ section.settings.onhow_studio_subheading }}</div>
{%- endif -%}
</div>
{%- endif -%}
{%- if section.settings.onhow_studio_mobile_behavior == 'static' -%}
<div class="onhow-studio-mobile-only" style="display: none;">
<video class="onhow-studio-static-video" controls {%- if onhow_studio_poster_src != blank -%} poster="{{ onhow_studio_poster_src }}"{%- endif -%}>
<source src="{{ onhow_studio_video_src_mobile }}" type="video/mp4">
</video>
</div>
<style>
@media (max-width: 749px) {
#{{ onhow_studio_section_id }} .onhow-studio-mobile-only { display: block; }
#{{ onhow_studio_section_id }} .onhow-studio-scroll-video-container,
#{{ onhow_studio_section_id }} .onhow-studio-scroll-video-spacer { display: none; }
}
</style>
{%- endif -%}
<div class="onhow-studio-video-wrapper">
<div class="onhow-studio-scroll-video-container">
{%- if section.settings.onhow_studio_heading != blank and section.settings.onhow_studio_text_position == 'overlay' -%}
<div class="onhow-studio-content-overlay">
<{{ section.settings.onhow_studio_heading_size }} class="onhow-studio-heading">{{ section.settings.onhow_studio_heading }}</{{ section.settings.onhow_studio_heading_size }}>
{%- if section.settings.onhow_studio_description != blank -%}
<div class="onhow-studio-description">{{ section.settings.onhow_studio_description }}</div>
{%- endif -%}
{%- if section.settings.onhow_studio_subheading != blank -%}
<div class="onhow-studio-subheading">{{ section.settings.onhow_studio_subheading }}</div>
{%- endif -%}
</div>
{%- endif -%}
<div class="onhow-studio-scroll-video-loading" id="{{ onhow_studio_section_id }}-loading">
<div class="onhow-studio-loading-spinner"></div>
</div>
<video
id="{{ onhow_studio_section_id }}-video"
class="onhow-studio-scroll-video-element onhow-studio-scroll-video-desktop"
preload="auto"
muted
playsinline
aria-label="{{ section.settings.onhow_studio_video_alt_text }}"
{%- if onhow_studio_poster_src != blank -%} poster="{{ onhow_studio_poster_src }}"{%- endif -%}
>
<source src="{{ onhow_studio_video_src }}" type="video/mp4">
</video>
{%- if section.settings.onhow_studio_mobile_video_file != blank and section.settings.onhow_studio_mobile_behavior != 'hide' -%}
<video
id="{{ onhow_studio_section_id }}-video-mobile"
class="onhow-studio-scroll-video-element onhow-studio-scroll-video-mobile"
preload="auto"
muted
playsinline
aria-label="{{ section.settings.onhow_studio_video_alt_text }}"
{%- if onhow_studio_poster_src != blank -%} poster="{{ onhow_studio_poster_src }}"{%- endif -%}
>
<source src="{{ onhow_studio_video_src_mobile }}" type="video/mp4">
</video>
{%- endif -%}
<div id="{{ onhow_studio_section_id }}-error" class="onhow-studio-scroll-video-error" style="display: none;">
<p>Failed to load video. Please check the video source.</p>
</div>
</div>
<div id="{{ onhow_studio_section_id }}-spacer" class="onhow-studio-scroll-video-spacer"></div>
</div>
{%- if section.settings.onhow_studio_heading != blank and section.settings.onhow_studio_text_position == 'below' -%}
<div class="onhow-studio-content-below">
<{{ section.settings.onhow_studio_heading_size }} class="onhow-studio-heading">{{ section.settings.onhow_studio_heading }}</{{ section.settings.onhow_studio_heading_size }}>
{%- if section.settings.onhow_studio_description != blank -%}
<div class="onhow-studio-description">{{ section.settings.onhow_studio_description }}</div>
{%- endif -%}
{%- if section.settings.onhow_studio_subheading != blank -%}
<div class="onhow-studio-subheading">{{ section.settings.onhow_studio_subheading }}</div>
{%- endif -%}
</div>
{%- endif -%}
{%- endif -%}
</div>
</div>
{%- unless onhow_studio_show_error -%}
<script>
(function() {
'use strict';
const onhowStudioCredit = atob("RGVzaWduZWQgYnkgT05IT1cgU3R1ZGlvIC0gU3Vic2NyaWJlIQ==");
console.log(`%c ${onhowStudioCredit}`, 'background: #222; color: #00ff00; padding: 4px; border-radius: 4px;');
const sectionId = '{{ onhow_studio_section_id }}';
const isMobile = window.innerWidth < 750;
const mobileVideoEl = document.getElementById(sectionId + '-video-mobile');
const desktopVideoEl = document.getElementById(sectionId + '-video');
const video = (isMobile && mobileVideoEl) ? mobileVideoEl : desktopVideoEl;
const spacer = document.getElementById(sectionId + '-spacer');
const container = document.querySelector('#' + sectionId + ' .onhow-studio-scroll-video-container');
const errorDiv = document.getElementById(sectionId + '-error');
const loadingDiv = document.getElementById(sectionId + '-loading');
const wrapper = document.querySelector('#' + sectionId);
if (!video || !spacer || !container || !wrapper) return;
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const isThemeEditor = window.Shopify && window.Shopify.designMode;
if (prefersReducedMotion) {
if (loadingDiv) loadingDiv.style.display = 'none';
video.controls = true;
video.muted = false;
return;
}
if (isThemeEditor) {
if (loadingDiv) loadingDiv.style.display = 'none';
video.controls = true;
video.muted = false;
return;
}
const mobileBehavior = '{{ section.settings.onhow_studio_mobile_behavior }}';
if (isMobile && mobileBehavior === 'static') {
if (loadingDiv) loadingDiv.style.display = 'none';
return;
}
const rootStyles = getComputedStyle(wrapper);
const desktopSpeed = parseInt(rootStyles.getPropertyValue('--onhow-studio-playback-speed')) || 500;
const mobileSpeed = parseInt(rootStyles.getPropertyValue('--onhow-studio-mobile-scroll-speed')) || 300;
const scrollMultiplier = parseFloat(rootStyles.getPropertyValue('--onhow-studio-scroll-multiplier')) || 1.0;
const playbackConst = isMobile ? mobileSpeed : desktopSpeed;
let animationFrameId = null;
let isIntersecting = false;
let scrollHeight = 0;
let sectionTop = 0;
let metadataTimeout = null;
function computeSectionTop() {
sectionTop = wrapper.getBoundingClientRect().top + window.pageYOffset;
}
computeSectionTop();
function setScrollHeight() {
if (!video.duration || isNaN(video.duration)) return;
let calculatedHeight = Math.floor(video.duration) * playbackConst * scrollMultiplier;
if (video.duration < 5) {
calculatedHeight = Math.max(calculatedHeight, 2500);
}
scrollHeight = calculatedHeight;
spacer.style.height = scrollHeight + 'px';
if (loadingDiv) loadingDiv.style.display = 'none';
}
function updateVideoPlayback() {
if (!isIntersecting || !video.duration) return;
const scrollPosition = window.pageYOffset - sectionTop;
if (scrollPosition >= -window.innerHeight && scrollPosition <= scrollHeight + window.innerHeight) {
const videoTime = Math.max(0, Math.min(scrollPosition / playbackConst, video.duration));
if (Math.abs(video.currentTime - videoTime) > 0.01) {
video.currentTime = videoTime;
}
}
}
function scrollLoop() {
if (isIntersecting) {
updateVideoPlayback();
animationFrameId = requestAnimationFrame(scrollLoop);
}
}
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
isIntersecting = entry.isIntersecting;
if (isIntersecting) {
computeSectionTop();
scrollLoop();
} else if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
animationFrameId = null;
}
});
}, {
rootMargin: '100px',
threshold: [0, 0.5, 1.0]
});
observer.observe(container);
video.addEventListener('loadedmetadata', function() {
setScrollHeight();
computeSectionTop();
if (metadataTimeout) clearTimeout(metadataTimeout);
});
metadataTimeout = setTimeout(function() {
if (!video.duration || isNaN(video.duration)) {
if (errorDiv) { errorDiv.style.display = 'block'; video.style.display = 'none'; }
if (loadingDiv) loadingDiv.style.display = 'none';
}
}, 10000);
video.addEventListener('error', function() {
if (errorDiv) { errorDiv.style.display = 'block'; video.style.display = 'none'; }
if (loadingDiv) loadingDiv.style.display = 'none';
if (animationFrameId) { cancelAnimationFrame(animationFrameId); animationFrameId = null; }
});
let resizeTimeout;
window.addEventListener('resize', function() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(function() {
setScrollHeight();
computeSectionTop();
}, 250);
});
const cleanup = function() {
if (animationFrameId) { cancelAnimationFrame(animationFrameId); animationFrameId = null; }
if (observer) observer.disconnect();
if (metadataTimeout) clearTimeout(metadataTimeout);
if (resizeTimeout) clearTimeout(resizeTimeout);
};
window.addEventListener('beforeunload', cleanup);
if (window.Shopify && window.Shopify.designMode) {
document.addEventListener('shopify:section:unload', cleanup);
}
})();
</script>
{%- endunless -%}
{% schema %}
{
"name": "Scroll Video",
"tag": "section",
"class": "onhow-studio-scroll-video-section",
"settings": [
{
"type": "header",
"content": "✨ Built by ONHOW Studio"
},
{
"type": "paragraph",
"content": "Get free sections & tutorials at youtube.com/@ONHOWStudio"
},
{
"type": "text",
"id": "onhow_studio_core_logic",
"label": "Section Architecture (Do Not Edit)",
"default": "built-by-onhow-studio",
"info": "Modifying this will break the section's CSS layout."
},
{
"type": "header",
"content": "― Core Settings ―"
},
{
"type": "color",
"id": "onhow_studio_bg_color",
"label": "Background Color",
"default": "#ffffff"
},
{
"type": "color",
"id": "onhow_studio_text_color",
"label": "Text Color",
"default": "#000000"
},
{
"type": "header",
"content": "Video Configuration"
},
{
"type": "video",
"id": "onhow_studio_video_file",
"label": "Video file"
},
{
"type": "url",
"id": "onhow_studio_video_url",
"label": "Video URL",
"info": "Used if video file is not provided"
},
{
"type": "image_picker",
"id": "onhow_studio_poster_image",
"label": "Poster image",
"info": "Shown while video loads"
},
{
"type": "text",
"id": "onhow_studio_video_alt_text",
"label": "Video description",
"default": "Scroll-controlled video presentation"
},
{
"type": "header",
"content": "Scroll Behavior"
},
{
"type": "range",
"id": "onhow_studio_playback_speed",
"min": 200,
"max": 1000,
"step": 50,
"unit": "px",
"label": "Scroll sensitivity",
"info": "Lower values = slower playback (pixels per second)",
"default": 500
},
{
"type": "range",
"id": "onhow_studio_scroll_multiplier",
"min": 0.5,
"max": 2,
"step": 0.1,
"label": "Scroll area multiplier",
"info": "Adjusts total scroll distance",
"default": 1
},
{
"type": "header",
"content": "Layout"
},
{
"type": "select",
"id": "onhow_studio_container_width",
"label": "Container width",
"options": [
{ "value": "full-width", "label": "Full width" },
{ "value": "page-width", "label": "Page width" },
{ "value": "narrow", "label": "Narrow (1000px)" }
],
"default": "full-width"
},
{
"type": "range",
"id": "onhow_studio_sticky_offset",
"min": 0,
"max": 200,
"step": 10,
"unit": "px",
"label": "Top spacing when sticky",
"default": 0
},
{
"type": "range",
"id": "onhow_studio_padding_top",
"min": 0,
"max": 100,
"step": 4,
"unit": "px",
"label": "Padding top",
"default": 36
},
{
"type": "range",
"id": "onhow_studio_padding_bottom",
"min": 0,
"max": 100,
"step": 4,
"unit": "px",
"label": "Padding bottom",
"default": 36
},
{
"type": "header",
"content": "Design"
},
{
"type": "range",
"id": "onhow_studio_border_radius",
"min": 0,
"max": 40,
"step": 4,
"unit": "px",
"label": "Video border radius",
"default": 0
},
{
"type": "select",
"id": "onhow_studio_shadow",
"label": "Video shadow",
"options": [
{ "value": "none", "label": "None" },
{ "value": "soft", "label": "Soft" },
{ "value": "strong", "label": "Strong" }
],
"default": "none"
},
{
"type": "color",
"id": "onhow_studio_overlay_color",
"label": "Overlay tint color",
"default": "#000000",
"info": "Only visible when text position is set to 'Overlay'"
},
{
"type": "range",
"id": "onhow_studio_overlay_opacity",
"min": 0,
"max": 100,
"step": 5,
"unit": "%",
"label": "Overlay tint opacity",
"info": "0% = no tint, 100% = solid color",
"default": 0
},
{
"type": "header",
"content": "Mobile Settings"
},
{
"type": "video",
"id": "onhow_studio_mobile_video_file",
"label": "Mobile video file",
"info": "Optional vertical (9:16) video for mobile. Falls back to primary video if empty."
},
{
"type": "select",
"id": "onhow_studio_mobile_behavior",
"label": "Mobile behavior",
"options": [
{ "value": "scroll", "label": "Scroll video (same as desktop)" },
{ "value": "static", "label": "Show video with controls" },
{ "value": "hide", "label": "Hide section on mobile" }
],
"default": "scroll"
},
{
"type": "range",
"id": "onhow_studio_mobile_scroll_speed",
"min": 100,
"max": 800,
"step": 50,
"unit": "px",
"label": "Mobile scroll speed",
"info": "Only applies if mobile behavior is 'Scroll video'",
"default": 300
},
{
"type": "header",
"content": "Content"
},
{
"type": "text",
"id": "onhow_studio_heading",
"label": "Heading"
},
{
"type": "richtext",
"id": "onhow_studio_description",
"label": "Description"
},
{
"type": "select",
"id": "onhow_studio_heading_size",
"label": "Heading size",
"options": [
{ "value": "h3", "label": "Small" },
{ "value": "h2", "label": "Medium" },
{ "value": "h1", "label": "Large" }
],
"default": "h2"
},
{
"type": "richtext",
"id": "onhow_studio_subheading",
"label": "Subheading"
},
{
"type": "select",
"id": "onhow_studio_text_position",
"label": "Text position",
"options": [
{ "value": "above", "label": "Above video" },
{ "value": "below", "label": "Below video" },
{ "value": "overlay", "label": "Overlay on video" }
],
"default": "above"
},
{
"type": "range",
"id": "onhow_studio_text_vertical_position",
"min": 10,
"max": 90,
"step": 5,
"unit": "%",
"label": "Text vertical position",
"info": "Only applies when text position is 'Overlay on video'",
"default": 50
}
],
"presets": [
{
"name": "Scroll Video (By ONHOW Studio)"
}
]
}
{% endschema %}
{%- comment -%}
<!-- Designed by ONHOW Studio - Anas El Medlaoui -->
{%- endcomment -%}

