Blog

How to create videos slider section in shopify store?


You can add videos slider section in your shopify store by adding custom code. Here is the code attached below.

<style>
  /* Outer section */
  #video-slider-{{ section.id }} {
    width: 100%;
    text-align: center;
  }
  /* Common container for heading and slider */
  #video-slider-{{ section.id }} .video-slider-container {
    margin: 0 auto;
  }
  #video-slider-{{ section.id }} .section-heading {
    font-size: {% if section.settings.heading_size == 'small' %}24px{% elsif section.settings.heading_size == 'medium' %}32px{% elsif section.settings.heading_size == 'large' %}40px{% endif %};
    text-align: {{ section.settings.heading_alignment }};
    margin-bottom: 20px;
    padding-left: {{ section.settings.heading_padding_left }}px;
  }
  #video-slider-{{ section.id }} .section-heading p {
    margin: 0;
  }
  /* Carousel wrapper */
  #video-slider-{{ section.id }} .video-slider-wrapper {
    position: relative;
    overflow: hidden;
  }
  #video-slider-{{ section.id }} .video-slider-slider {
    overflow: hidden;
    position: relative;
  }
  #video-slider-{{ section.id }} .slider-track {
    display: flex;
    transition: transform 0.5s ease-in-out;
    will-change: transform;
  }
  /* Desktop: Each slide's width based on visible_slides setting */
  #video-slider-{{ section.id }} .slide {
    flex: 0 0 calc(100% / {{ section.settings.visible_slides }});
    box-sizing: border-box;
    padding-top: 20px;
    padding-bottom: 20px;
    padding-left: {{ section.settings.slide_spacing | divided_by: 2.0 }}px;
    padding-right: {{ section.settings.slide_spacing | divided_by: 2.0 }}px;
  }
  /* Mobile override: use visible_mobile setting */
  @media (max-width: 767px) {
    #video-slider-{{ section.id }} .slide {
      flex: 0 0 calc(100% / {{ section.settings.visible_mobile }});
    }
  }
  #video-slider-{{ section.id }} .media-element {
    width: 100%;
    object-fit: cover;
    display: block;
    {% case section.settings.media_design %}
      {% when "square" %}
        aspect-ratio: 1 / 1;
      {% when "portrait" %}
        aspect-ratio: 2 / 3;
      {% else %}
        /* adapt */
        height: auto;
    {% endcase %}
  }
  {% if section.settings.enable_video_border_radius %}
  #video-slider-{{ section.id }} video.media-element {
    border-radius: {{ section.settings.video_border_radius }}px;
    overflow: hidden;
  }
  {% endif %}
  /* Shadow is applied to the wrapper hugging the video itself, not the padded
     slide box, so it's visible and isn't clipped by the slider's overflow:hidden */
  {% if section.settings.media_shadow %}
  #video-slider-{{ section.id }} .video-wrapper {
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
    {% if section.settings.enable_video_border_radius %}
    border-radius: {{ section.settings.video_border_radius }}px;
    {% endif %}
  }
  {% endif %}
  /* Arrow Buttons */
  #video-slider-{{ section.id }} .arrow {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    background: {{ section.settings.arrow_bg_color }};
    color: {{ section.settings.arrow_icon_color }};
    border: none;
    font-size: 24px;
    padding: 10px;
    cursor: pointer;
    z-index: 10;
    border-radius: {% if section.settings.arrow_shape == 'circle' %}50%{% else %}0{% endif %};

    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0px 0px;
    width: 50px;
    height: 50px;
  }
  #video-slider-{{ section.id }} .left-arrow {
    left: 10px;
  }
  #video-slider-{{ section.id }} .right-arrow {
    right: 10px;
  }
  /* Custom video controls */
  #video-slider-{{ section.id }} .video-wrapper {
    position: relative;
  }
  #video-slider-{{ section.id }} .video-control-btn {
    position: absolute;
    background: rgba(0, 0, 0, 0.55);
    border: none;
    color: #fff;
    cursor: pointer;
    border-radius: 50%;
    z-index: 5;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
  }
  #video-slider-{{ section.id }} .video-control-btn svg {
    width: 55%;
    height: 55%;
  }
  #video-slider-{{ section.id }} .video-play-pause {
    width: 50px;
    height: 50px;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
  #video-slider-{{ section.id }} .video-mute {
    width: 34px;
    height: 34px;
    bottom: 15px;
    right: 10px;
  }
  #video-slider-{{ section.id }} .video-play-pause .icon-play,
  #video-slider-{{ section.id }} .video-play-pause .icon-pause,
  #video-slider-{{ section.id }} .video-mute .icon-volume,
  #video-slider-{{ section.id }} .video-mute .icon-mute {
    display: none;
  }
  #video-slider-{{ section.id }} .video-wrapper.paused .video-play-pause .icon-play {
    display: block;
  }
  #video-slider-{{ section.id }} .video-wrapper:not(.paused) .video-play-pause .icon-pause {
    display: block;
  }
  #video-slider-{{ section.id }} .video-wrapper.muted .video-mute .icon-mute {
    display: block;
  }
  #video-slider-{{ section.id }} .video-wrapper:not(.muted) .video-mute .icon-volume {
    display: block;
  }
</style>

{% assign cloneCount = section.settings.visible_slides %}
{% assign total = section.blocks.size %}

<div id="video-slider-{{ section.id }}" class="video-slider-section" style="background-color: {{ section.settings.section_bg_color }}; padding-top: {{ section.settings.section_padding_top }}px; padding-bottom: {{ section.settings.section_padding_bottom }}px;">
  <div class="video-slider-container" style="width: {% if section.settings.full_width %}100%{% else %}80%{% endif %}; margin: 0 auto;">
    {% if section.settings.section_heading != blank %}
      <div class="section-heading">{{ section.settings.section_heading }}</div>
    {% endif %}
    <div class="video-slider-wrapper">
      {% if section.settings.show_arrows %}
        <button class="arrow left-arrow" aria-label="Previous">❮</button>
      {% endif %}
      <div class="video-slider-slider">
        <div class="slider-track">
          {% if total > 0 %}
            {%- comment -%}
              Build one combined list: [last cloneCount blocks] + [all real blocks] + [first cloneCount blocks].
              This replaces three copy-pasted loops with a single loop, using Shopify's slice/concat filters.
            {%- endcomment -%}
            {% assign offset_value = total | minus: cloneCount %}
            {% if offset_value < 0 %}
              {% assign offset_value = 0 %}
            {% endif %}
            {% assign end_blocks = section.blocks | slice: offset_value, cloneCount %}
            {% assign start_blocks = section.blocks | slice: 0, cloneCount %}
            {% assign combined_blocks = end_blocks | concat: section.blocks | concat: start_blocks %}
            {% assign end_blocks_count = end_blocks.size %}
            {% assign clone_start_cutoff = end_blocks_count | plus: total %}

            {% for block in combined_blocks %}
              {% assign is_clone = false %}
              {% if forloop.index0 < end_blocks_count or forloop.index0 >= clone_start_cutoff %}
                {% assign is_clone = true %}
              {% endif %}
              <div class="slide{% if is_clone %} clone{% endif %}"{% if is_clone %} aria-hidden="true" tabindex="-1"{% endif %}>
                {% if block.settings.media %}
                  <div class="video-wrapper muted">
                    {{ block.settings.media | video_tag: class: 'media-element js-video', autoplay: false, loop: true, muted: true, controls: false, playsinline: true, image_size: '600x' }}
                    {% if section.settings.show_video_controls %}
                      <button type="button" class="video-control-btn video-play-pause" aria-label="Play or pause video">
                        <svg class="icon-play" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M8 5v14l11-7z"/></svg>
                        <svg class="icon-pause" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M6 5h4v14H6zM14 5h4v14h-4z"/></svg>
                      </button>
                      <button type="button" class="video-control-btn video-mute" aria-label="Mute or unmute video">
                        <svg class="icon-volume" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M3 10v4h4l5 5V5L7 10H3zm13.5 2A4.5 4.5 0 0 0 14 7.97v8.05A4.48 4.48 0 0 0 16.5 12z"/></svg>
                        <svg class="icon-mute" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><path d="M3 10v4h4l5 5V5L7 10H3zm13.59 2 2.7-2.71-1.41-1.41L15.17 10l-2.7-2.71-1.42 1.42L13.76 11l-2.71 2.71 1.42 1.42L15.17 12.4l2.71 2.71 1.41-1.41z"/></svg>
                      </button>
                    {% endif %}
                  </div>
                {% endif %}
              </div>
            {% endfor %}
          {% endif %}
        </div>
      </div>
      {% if section.settings.show_arrows %}
        <button class="arrow right-arrow" aria-label="Next">❯</button>
      {% endif %}
    </div>
  </div>
</div>

<script>
document.addEventListener("DOMContentLoaded", function() {
  var container = document.getElementById("video-slider-{{ section.id }}");
  if (!container) return;
  var sliderTrack = container.querySelector(".slider-track");
  var slides = container.querySelectorAll(".slide");
  if (slides.length === 0) return;

  var cloneCount = {{ cloneCount | json }};
  var visibleSlides = window.innerWidth <= 767 ? {{ section.settings.visible_mobile }} : {{ section.settings.visible_slides }};
  var slider = container.querySelector(".video-slider-slider");
  var slideWidth = slider.offsetWidth / visibleSlides;

  var currentIndex = cloneCount;

  function updateSlidePosition() {
    sliderTrack.style.transform = "translateX(-" + (currentIndex * slideWidth) + "px)";
  }

  updateSlidePosition();

  function nextSlide() {
    currentIndex++;
    sliderTrack.style.transition = "transform 0.5s ease-in-out";
    updateSlidePosition();
    if (currentIndex >= slides.length - cloneCount) {
      setTimeout(function() {
        sliderTrack.style.transition = "none";
        currentIndex = cloneCount;
        updateSlidePosition();
        void sliderTrack.offsetWidth;
        sliderTrack.style.transition = "transform 0.5s ease-in-out";
      }, 500);
    }
  }

  function prevSlide() {
    currentIndex--;
    sliderTrack.style.transition = "transform 0.5s ease-in-out";
    updateSlidePosition();
    if (currentIndex < cloneCount) {
      setTimeout(function() {
        sliderTrack.style.transition = "none";
        currentIndex = slides.length - cloneCount - 1;
        updateSlidePosition();
        void sliderTrack.offsetWidth;
        sliderTrack.style.transition = "transform 0.5s ease-in-out";
      }, 500);
    }
  }

  var rightArrow = container.querySelector(".right-arrow");
  var leftArrow = container.querySelector(".left-arrow");
  if (rightArrow) {
    rightArrow.addEventListener("click", nextSlide);
  }
  if (leftArrow) {
    leftArrow.addEventListener("click", prevSlide);
  }

  var autoplay = {{ section.settings.auto_slide | json }};
  var autoplaySpeed = {{ section.settings.auto_slide_speed | json }};
  if (autoplay) {
    setInterval(nextSlide, autoplaySpeed);
  }

  // Debounced resize handler
  var resizeTimeout;
  window.addEventListener("resize", function() {
    clearTimeout(resizeTimeout);
    resizeTimeout = setTimeout(function() {
      visibleSlides = window.innerWidth <= 767 ? {{ section.settings.visible_mobile }} : {{ section.settings.visible_slides }};
      slideWidth = container.querySelector(".video-slider-slider").offsetWidth / visibleSlides;
      sliderTrack.style.transition = "none";
      updateSlidePosition();
    }, 150);
  });

  // Custom play/pause and mute/unmute controls
  var videoWrappers = container.querySelectorAll(".video-wrapper");
  videoWrappers.forEach(function(wrapper) {
    var video = wrapper.querySelector("video");
    if (!video) return;
    var playPauseBtn = wrapper.querySelector(".video-play-pause");
    var muteBtn = wrapper.querySelector(".video-mute");

    wrapper.classList.toggle("paused", video.paused);
    wrapper.classList.toggle("muted", video.muted);

    video.addEventListener("play", function() {
      wrapper.classList.remove("paused");
    });
    video.addEventListener("pause", function() {
      wrapper.classList.add("paused");
    });
    video.addEventListener("volumechange", function() {
      wrapper.classList.toggle("muted", video.muted);
    });

    if (playPauseBtn) {
      playPauseBtn.addEventListener("click", function(e) {
        e.stopPropagation();
        if (video.paused) {
          video.play();
        } else {
          video.pause();
        }
      });
    }
    if (muteBtn) {
      muteBtn.addEventListener("click", function(e) {
        e.stopPropagation();
        video.muted = !video.muted;
      });
    }
  });

  // Lazy playback: only decode/stream video that's actually visible inside the
  // slider viewport. Previously every slide (including clones) autoplayed at
  // once, which could mean well over a dozen simultaneous video downloads.
  var observerRoot = container.querySelector(".video-slider-wrapper");
  if ("IntersectionObserver" in window) {
    var io = new IntersectionObserver(function(entries) {
      entries.forEach(function(entry) {
        var video = entry.target;
        if (entry.isIntersecting) {
          var playPromise = video.play();
          if (playPromise !== undefined) {
            playPromise.catch(function() {});
          }
        } else {
          video.pause();
        }
      });
    }, { root: observerRoot, threshold: 0.5 });

    container.querySelectorAll(".js-video").forEach(function(video) {
      io.observe(video);
    });
  } else {
    // Fallback for very old browsers: just play everything as before.
    container.querySelectorAll(".js-video").forEach(function(video) {
      video.play().catch(function() {});
    });
  }
});
</script>

{% schema %}
{
  "name": "Video Slider",
  "settings": [
    {
      "type": "richtext",
      "id": "section_heading",
      "label": "Section Heading",
      "default": "<p>Video Slider</p>"
    },
    {
      "type": "range",
      "id": "heading_padding_left",
      "label": "Heading Left Padding (px)",
      "min": 0,
      "max": 100,
      "step": 1,
      "default": 20
    },
    {
      "type": "select",
      "id": "heading_alignment",
      "label": "Section Heading Alignment",
      "options": [
        { "value": "left", "label": "Left" },
        { "value": "center", "label": "Center" },
        { "value": "right", "label": "Right" }
      ],
      "default": "center"
    },
    {
      "type": "select",
      "id": "heading_size",
      "label": "Section Heading Size",
      "options": [
        { "value": "small", "label": "Small" },
        { "value": "medium", "label": "Medium" },
        { "value": "large", "label": "Large" }
      ],
      "default": "medium"
    },
    {
      "type": "checkbox",
      "id": "full_width",
      "label": "Full Width Section (applies to heading & slider)",
      "default": false
    },
    {
      "type": "color",
      "id": "section_bg_color",
      "label": "Section Background Color",
      "default": "#ffffff"
    },
    {
      "type": "range",
      "id": "section_padding_top",
      "label": "Section Padding Top (px)",
      "min": 0,
      "max": 200,
      "step": 5,
      "default": 40
    },
    {
      "type": "range",
      "id": "section_padding_bottom",
      "label": "Section Padding Bottom (px)",
      "min": 0,
      "max": 200,
      "step": 5,
      "default": 40
    },
    {
      "type": "checkbox",
      "id": "auto_slide",
      "label": "Enable Auto Slide",
      "default": true
    },
    {
      "type": "range",
      "id": "auto_slide_speed",
      "label": "Auto Slide Speed (ms)",
      "min": 100,
      "max": 9000,
      "step": 100,
      "default": 6000
    },
    {
      "type": "checkbox",
      "id": "show_arrows",
      "label": "Show Left/Right Arrows",
      "default": true
    },
    {
      "type": "checkbox",
      "id": "show_video_controls",
      "label": "Show Play/Pause and Mute Buttons",
      "default": true
    },
    {
      "type": "select",
      "id": "arrow_shape",
      "label": "Arrow Shape",
      "options": [
        { "value": "circle", "label": "Circle" },
        { "value": "square", "label": "Square" }
      ],
      "default": "circle"
    },
    {
      "type": "color",
      "id": "arrow_bg_color",
      "label": "Arrow Background Color",
      "default": "#000000"
    },
    {
      "type": "color",
      "id": "arrow_icon_color",
      "label": "Arrow Icon Color",
      "default": "#ffffff"
    },
    {
      "type": "range",
      "id": "visible_slides",
      "label": "Number of Visible Slides (Desktop)",
      "min": 1,
      "max": 8,
      "step": 1,
      "default": 4
    },
    {
      "type": "range",
      "id": "visible_mobile",
      "label": "Number of Visible Slides (Mobile)",
      "min": 1,
      "max": 8,
      "step": 1,
      "default": 1
    },
    {
      "type": "range",
      "id": "slide_spacing",
      "label": "Spacing Between Slides (px)",
      "min": 0,
      "max": 80,
      "step": 2,
      "default": 40
    },
    {
      "type": "select",
      "id": "media_design",
      "label": "Video Shape",
      "options": [
        { "value": "square", "label": "Square" },
        { "value": "portrait", "label": "Portrait" },
        { "value": "adapt", "label": "Adapt" }
      ],
      "default": "adapt"
    },
    {
      "type": "checkbox",
      "id": "media_shadow",
      "label": "Enable Video Shadow",
      "default": false
    },
    {
      "type": "checkbox",
      "id": "enable_video_border_radius",
      "label": "Enable Video Border Radius",
      "default": false
    },
    {
      "type": "range",
      "id": "video_border_radius",
      "label": "Video Border Radius (px)",
      "min": 1,
      "max": 50,
      "step": 1,
      "default": 12
    }
  ],
  "blocks": [
    {
      "type": "carousel_video",
      "name": "Carousel Video",
      "settings": [
        {
          "type": "video",
          "id": "media",
          "label": "Video"
        }
      ]
    }
  ],
  "max_blocks": 10,
  "presets": [
    {
      "name": "Video Slider"
    }
  ]
}
{% endschema %}

Leave a Reply

Your email address will not be published. Required fields are marked *