Product Slider for Dawn Theme - No apps or subscript- Just a little bit of code

Product Slider for Dawn Theme - No apps or subscript- Just a little bit of code

This only works with Dawn 2.4 and lower. Check this video on how to see your theme version link.
Did you use Dawn theme and was disappointed that they do not have a product slider?
Don't worry. In this tutorial, we will create one.
Recommendations: I also created a code to transform Dawn product page like Debut theme with a slider. Check link.
  1. Go to your Online store > Themes > Actions > Edit code
  2. Go to Section folder and open the main-product.liquid
  3. Find <slider-component> block and comment it out or delete it if you want

Comment it out by placing “<!--” before the slider-component and “-->” after the slider-component. Code should look like below

 <!-- <slider-component>                                              </slider-component> -->


      4. Before the commented out <slider-component>, add the code below

  <div class="slider-container" >
    <a class="skip-to-content-link button visually-hidden" href="#ProductInfo-{{ }}">
{{ "accessibility.skip_to_product_info" | t }}
    <ul class="large-image" id="large-image">
        {%- for media in -%}
        <li class="large-image-item product__media-item grid__item slider__slide
{% if media.media_type != 'image' %} hide-modal {% endif %}"
data-media-id="{{ }}-{{ }}">
{% render 'product-thumbnail', media: media, position: forloop.index, loop: section.settings.enable_video_looping, modal_id:, xr_button: true %}
       {%- endfor -%}

<slider-component >
   <ul class="product-slider-box slider" role="list">

 {%- assign variant_images = product.images| where: 'attached_to_variant?', true | map: 'src' -%}

{%- for media in -%}
      <li class="product-slider slider__slide" onclick="newLargeImage(this)" data-media-id="{{ }}-{{ }}"

{% if section.settings.hide_variants and variant_images contains media.src %} style="display: none;" {% endif %}>

{% if media.media_type == 'video' %}
          <div class="video-btn" style="display: block" >
             <span class="product__media-icon motion-reduce v-btn" aria-hidden="true">
{%- liquid
case media.media_type
when 'video' or 'external_video'
render 'icon-play'
when 'model'
render 'icon-3d-model'
render 'icon-zoom'
     <img class="slide-image"
src="{{ media.preview_image | img_url: 'large' }}"
alt="{{media.alt }}">
{% else %}
     <img class="slide-image"
src="{{ media.preview_image | img_url: 'large' }}"
alt="{{ media.alt}}">
{% endif %}
{% endfor %}
<div class="slider-buttons {% if < 5 %}hidden{% endif %}" style="display: flex">
   <button type="button" class="slider-button slider-button--prev bigger-slider" name="previous" aria-label="{{ 'accessibility.previous_slide' | t }}">{% render 'icon-caret' %}</button>
      <div class="slider-counter caption">
           <span class="slider-counter--current">1</span>
           <span aria-hidden="true"> / </span>
           <span class="visually-hidden">{{ 'accessibility.of' | t }}</span>
           <span class="slider-counter--total">{% if section.settings.hide_variants %}{{ | minus: variant_images.size | plus: 1 }}{% else %}{{ }}{% endif %}</span>
    <button type="button" class="slider-button slider-button--next bigger-slider" name="next" aria-label="{{ 'accessibility.next_slide' | t }}">{% render 'icon-caret' %}</button>

       5. On the top part, paste the code below, and click SAVE


window.onload = (event) => {
document.querySelector("li:nth-child(1) > img").classList.add('active-thumb');

      function newLargeImage(x) {
            let clickedImage = x.dataset.mediaId;
            const newImage = document.querySelector(`[data-media-id="${clickedImage}"]`);
            const parentData = newImage.parentElement;

   = "block";

.forEach(thumb => thumb. classList.remove('active-thumb'));
const sliderComp = document.querySelector("slider-component");
document.querySelector(`[data-media-id="${clickedImage}"] > img`).classList.add('active-thumb');



       6. I see that the component-slider.css is also being use for multi-column section, therefore, we have to create a new .css file. Go to Asset folder, click 'create new asset', create blank. Name the file 'product-slider'. File should show like below



     7. Now open, the created CSS folder and paste the code below.

 .slider-container {
margin: 0 auto;
width: 100%;
overflow: auto;
display: flex;
flex-flow: column wrap;
align-items: center;
position: relative;

.large-image {
width: 100%;
position: relative;

.large-image-item {
max-width: 100%;
min-width: 50%;
max-height: 100%;
padding: 0;

display: none !important;

ul {
padding-inline-start: 0px !important;

slider-component {
position: relative;
display: block;

.slider__slide {
scroll-snap-align: start;
flex-shrink: 0;

.product-slider-box {
flex-wrap: inherit;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
margin-bottom: 1rem;
width: 100%;
display: flex;

.product-slider {
height: 100%;
width: 23%;
display: inline-block;

margin-left: 1rem;

.slide-image {
width: 100%;
height: 100%;
object-fit: cover;

.slider {
scrollbar-color: rgb(var(--color-foreground)) rgba(var(--color-foreground), 0.04);
-ms-overflow-style: none;
scrollbar-width: none;

.slider::-webkit-scrollbar {
height: 0.4rem;
width: 0.4rem;
display: none;

.no-js .slider {
-ms-overflow-style: auto;
scrollbar-width: auto;

.no-js .slider::-webkit-scrollbar {
display: initial;

.slider::-webkit-scrollbar-thumb {
background-color: rgb(var(--color-foreground));
border-radius: 0.4rem;
border: 0;

.slider::-webkit-scrollbar-track {
background: rgba(var(--color-foreground), 0.04);
border-radius: 0.4rem;

.slider-counter {
margin: 0 1.2rem;

.slider-buttons {
display: flex;
align-items: center;
justify-content: center;

.slider-button {
color: rgba(var(--color-foreground), 0.75);
background: transparent;
border: none;
cursor: pointer;
width: 44px;
height: 44px;

.slider-button:not([disabled]):hover {
color: rgb(var(--color-foreground));

.slider-button .icon {
height: 0.6rem;

.slider-button[disabled] .icon {
color: rgba(var(--color-foreground), 0.3);

.slider-button--next .icon {
margin-right: -0.2rem;
transform: rotate(-90deg) translateX(0.15rem);

.slider-button--prev .icon {
margin-left: -0.2rem;
transform: rotate(90deg) translateX(-0.15rem);

.slider-button--next:not([disabled]):hover .icon {
transform: rotate(-90deg) translateX(0.15rem) scale(1.07);

.slider-button--prev:not([disabled]):hover .icon {
transform: rotate(90deg) translateX(-0.15rem) scale(1.07);

/* video button when image is a video type */
.video-btn {
width: 100%;
height: 100%;
position: relative;

.v-btn {
top: 2% !important;
left: 2% !important;

.hide-modal modal-opener {
display: none;

.active-thumb {
opacity: 1 !important;
border: solid 2px var(--gradient-base-accent-1);
box-sizing: border-box;

.slide-image {
opacity: .5;


    8. Next, go back to the main-product.liquid. At the top part, comment out this code. You can also just delete it. To comment it out, place (<!-- ) before the code and (--->) after. Just like we did in the slider-component. Code should look like this.

 <!--{{ 'component-slider.css' | asset_url | stylesheet_tag }}-->

add this after. 

 {{ 'product-slider.css' | asset_url | stylesheet_tag }}


    9.  We need to go to the Asset folder again, and open global.js. Find the slider-component. Since slider component is a global code, meaning, some section also uses the same code. We have to add an if statement. Please disregard the video regarding this section in global.js.

At the SliderComponent constructor add the code below.

 this.productSlider = this.querySelector('.product-slider-box');

   10. At the initPages function we need to change the totalPages. Replace the code below:

this.totalPages = sliderItemsToShow.length - this.slidesPerPage + 1;

 with this

  if (this.productSlider) { this.totalPages = sliderItemsToShow.length - this.slidesPerPage + 4} else {
this.totalPages = sliderItemsToShow.length - this.slidesPerPage + 1;

    10.  Lastly, at the update function we need to change the currentPage, change the 1 into 4. Replace the code below, and click SAVE

this.currentPage = Math.round(this.slider.scrollLeft / this.sliderLastItem.clientWidth) + 1;

 to this

if (this.productSlider) {this.currentPage = Math.round(this.slider.scrollLeft / this.sliderLastItem.clientWidth) + 4} else {
this.currentPage = Math.round(this.slider.scrollLeft / this.sliderLastItem.clientWidth) + 1;


The global.js code should look like this:


That's it! You just transform the product page of Dawn theme. Let me know if you have questions or having issues with the code so we can fix it and have an updated code. (",)


Update 09/22/21: I end up changing the the code in the Asset/global.js so we do not break the slider component if we use it in the other section

I change the CSS code and remove the resize observer. Large-image will be the same height with the large-image-item.

Update 09/23/21: Issues of having two large image and slider missing fixed. Updated code to use feature hide_variants 

Update 09/25/21: Fix the issue with thumbnail disappears when adding a section that uses a slider-component. Updated the code in the step #4.

Update 09/26/21: Added a video play button when thumbnail image is a video

Update 09/30/21: Fix the issue regarding the video button. Reposition the codes for the video-btn and added some css codes

 Update 10/01/21: Fix the issue of stacking large images in mobile. I added a resizeObserver in the Javascript to fix the issue of big gaps between the large-image and the slider. If you don't want it you just delete the code

Update 10/03/21: Added overflow: hidden to large-image css. I would recommend not to have product images with extreme height as your first variant image. Also added some CSS so when active, thumbnail image will have border box and opacity is 1. See code in green. Thumbnail border color is dependent on your var(--gradient-base-accent-1)

Update 10/04/21: Change the v-btn in the product-slider.css file due to issue when having a mobile video

 Update 10/10/21: I know I fix the issue regarding the space between the large image and the slider. I did remove the resizeObserver and also the padding-bottom of the large image to fix this. I updated the code

Update 10/11/21: I change how the border and opacity is applied. Please see the highlighted green code

Update 10/15/21: I added an onload function so when the window loaded the first image in the thumbnail will get the active property. Code is pink. 

Also added a code for those who still want the option to hide the variants when variants selected. (NOTE: this is the original code from Dawn). See code in blue.

Back to blog


Hi @CLIMBINGMOUNTAINS. Have you tried adjusting your media in the product section? Make your first photo as the large media.


Thank you for the prompt reply made! Sorry if I wasn’t clear in my explanation. What I mean is, for example, in your video, the order of the bike pedals on your product slider is grey > red > white > black (see 6:24 in the video). What if I want the picture of the red pedal to appear as the first picture (e.g. in this order red > white > grey > black)?

I am selling something with 3 variants in red, blue and green colours. I have a total of 4 images (1 for each colours, and 1 that shows all 3 variants in the same photo). Currently, the first picture in my slider is the one for the red variant, followed by the photo with all 3 variants as the second picture in the slider. I want the photo with all 3 variants to appear as the first picture in the slider, but I’m having some difficulty doing so. I tried to reorder my pictures and variants from my shopify admin console, but that doesn’t seem to solve it.


Hi everyone. Sorry. Shopify has a very unfriendly way of addressing comments.

@Charles – Yes, we can but that would be messing up with the input in the javascript. It is tedious to do so since we have to assign every variant images to a variant.

@eunice – Thank you so much. You can put auto on the margin, I just have the code updated. Re: the slider, the slider component is relying on the width of the li, which is our product images. If the images is not fully shown, it will not be counted. That is why, we have to set the width of the images that it will fully shown in the slider

@climbingmountains – I am not sure what you mean by reordering the variants. The Dawn has its function to hide_variants. I am pretty sure you can reorder the image in the product. Please see this link that talks about reordering
@charles – will do


One issue I met: if you have video in the slider, the play button won’t show on the slider thumbnail, so the customer won’t know it’s a video. Please look into this. Thanks


Hi, I was wondering, is it possible to re-order the sequence of photos that appear in the slider?


Leave a comment