Compatibility: Compatible with theme version 2.5 and Shopify 3.0 themes. Please use the appropriate Step #2 code
Hi,
Many of you might have encountered trouble in applying the code that I have previously. There was a new update with Dawn theme, theme version is 2.5.0. I know Dawn theme will have more updates in the future. Therefore, I made the code that will not be affect with the future updates. With that being said, it does not matter which theme version you have. This code should work.
To start.
- Go to your Online store > Themes > Actions > Edit code
- Go to Section folder and created a new section, name it "featured-slider". Then, paste the code below.
{{ 'component-card.css' | asset_url | stylesheet_tag }} {{ 'component-price.css' | asset_url | stylesheet_tag }} {{ 'component-product-grid.css' | asset_url | stylesheet_tag }} {{ 'featured-slider.css' | asset_url | stylesheet_tag }} <link rel="stylesheet" href="{{ 'component-slider.css' | asset_url }}" media="print" onload="this.media='all'"> <link rel="stylesheet" href="{{ 'template-collection.css' | asset_url }}" media="print" onload="this.media='all'"> <noscript>{{ 'template-collection.css' | asset_url | stylesheet_tag }}</noscript> {%- liquid assign products_to_display = section.settings.collection.all_products_count assign swipe_on_mobile = true if section.settings.collection.all_products_count > section.settings.products_to_show assign products_to_display = section.settings.products_to_show assign more_in_collection = true endif -%} <div class="collection"> <div class="featured-title-wrapper{% if section.settings.title == blank %} title-wrapper-with-link--no-heading{% endif %}"> {% if section.settings.title != blank %} <h2 class="featured-title">{{ section.settings.title | escape }}</h2> {% endif %} {% if section.settings.show_view_all %} <a href="{{ section.settings.collection.url }}" class="button">{{ 'sections.featured_collection.view_all' | t }}</a> {% endif %} </div> <featured-slider-component style="--border-color: {{section.settings.border_color}};"> <ul id="Slider-{{ section.id }}" class="featured-grid product-grid {% if section.settings.collection.all_products_count > 2 and swipe_on_mobile and section.settings.products_to_show > 2 %} slider slider--tablet grid--peek{% endif %} {% if section.settings.show_view_all and section.settings.collection.products.size > section.settings.products_to_show %} negative-margin--small{% endif %}" role="list"> {%- for product in section.settings.collection.products limit: section.settings.products_to_show -%} <li id="Slide-{{ section.id }}-{{ forloop.index }}" data-image="{{forloop.index0}}" class="grid--col {% if section.settings.collection.all_products_count > 2 and swipe_on_mobile and section.settings.products_to_show > 2 %} slider__slide{% endif %}"> {% render 'card-product', card_product: product, media_aspect_ratio: section.settings.image_ratio, show_secondary_image: section.settings.show_secondary_image, show_vendor: section.settings.show_vendor, show_rating: section.settings.show_rating %} </li> {%- else -%} {%- for i in (1..4) -%} <li class="grid__item"> {% render 'card-product', show_vendor: section.settings.show_vendor %} </li> {%- endfor -%} {%- endfor -%} </ul> {%- if section.settings.collection.all_products_count > 2 and swipe_on_mobile and section.settings.products_to_show > 2 -%} <div class="slideshow__controls slider-buttons no-js-hidden" style="display: flex"> <button type="button" class="slider-button slider-button--prev" data-step="1" name="previous" aria-label="{{ 'sections.slideshow.previous_slideshow' | t }}" aria-controls="Slider-{{ section.id }}">{% render 'icon-caret' %}</button> <div class="slider-counter slider-counter--{{ section.settings.slider_visual }}{% if section.settings.slider_visual == 'numbers' %} caption{% endif %}"> <div class="counter--mobile"> <span class="slider-counter--current">1</span> <span aria-hidden="true"> / </span> <span class="slider-counter--total"> {% if section.settings.products_to_show < section.settings.collection.products %} {{section.settings.products_to_show }} {% else %} {{section.settings.collection.all_products_count}} {% endif %} </span> </div> <div class="slideshow__control-wrapper slider"> {%- for product in section.settings.collection.products limit: section.settings.products_to_show -%} <button class="slider-counter__link slider-counter__link--{{ section.settings.slider_visual }} link" data-dot="{{forloop.index0}}" style="padding: 1rem; width: 100%" aria-label="{{ 'sections.slideshow.load_slide' | t }} {{ forloop.index }} {{ 'general.slider.of' | t }} {{ forloop.length}}" aria-controls="Slider-{{ section.id }}"> {%- if section.settings.slider_visual == 'numbers' -%}{{ forloop.index }}{% else %}<span class="dot"></span>{%- endif -%} </button> {%- endfor -%} </div> </div> <button type="button" class="slider-button slider-button--next" name="next" data-step="1" aria-label="{{ 'sections.slideshow.next_slideshow' | t }}" aria-controls="Slider-{{ section.id }}">{% render 'icon-caret' %}</button> </div> <noscript> <div class="slider-buttons" style="display: flex"> <div class="slider-counter"> {%- for product in section.settings.collection.products limit: section.settings.products_to_show -%} <a href="#Slide-{{ section.id }}-{{ forloop.index }}" data-dot="{{forloop.index}}" class="slider-counter__link link" aria-label="{{ 'sections.slideshow.load_slide' | t }} {{ forloop.index }} {{ 'general.slider.of' | t }} {{ forloop.length}}"> {{ forloop.index }} </a> {%- endfor -%} </div> </div> </noscript> {%- endif -%} </featured-slider-component> </div> {% schema %} { "name": "Featured Slider", "tag": "section", "class": "spaced-section", "settings": [ { "type": "text", "id": "title", "default": "Featured collection", "label": "t:sections.featured-collection.settings.title.label" }, { "type": "collection", "id": "collection", "label": "t:sections.featured-collection.settings.collection.label" }, { "type": "range", "id": "products_to_show", "min": 2, "max": 99, "step": 1, "default": 4, "label": "t:sections.featured-collection.settings.products_to_show.label" }, { "type": "checkbox", "id": "show_view_all", "default": true, "label": "t:sections.featured-collection.settings.show_view_all.label" }, { "type": "header", "content": "t:sections.featured-collection.settings.header.content" }, { "type": "select", "id": "image_ratio", "options": [ { "value": "adapt", "label": "t:sections.featured-collection.settings.image_ratio.options__1.label" }, { "value": "portrait", "label": "t:sections.featured-collection.settings.image_ratio.options__2.label" }, { "value": "square", "label": "t:sections.featured-collection.settings.image_ratio.options__3.label" } ], "default": "adapt", "label": "t:sections.featured-collection.settings.image_ratio.label" }, { "type": "checkbox", "id": "show_secondary_image", "default": false, "label": "show secondary image" }, { "type": "checkbox", "id": "add_image_padding", "default": false, "label": "add image padding" }, { "type": "checkbox", "id": "show_image_outline", "default": true, "label": "show image outline" }, { "type": "checkbox", "id": "show_vendor", "default": false, "label": "show vendor" }, { "type": "checkbox", "id": "show_rating", "default": false, "label": "show product rating", "info": "To display a rating, add a product rating app. Learn more" }, { "type": "color", "id": "border_color", "label": "border color", "default": "#eee" }, { "type": "select", "id": "slider_visual", "options": [ { "value": "dots", "label": "dots" }, { "value": "numbers", "label": "numbers" } ], "default": "numbers", "label": "numbers" } ], "presets": [ { "name": "Featured Collection Slider" } ] } {% endschema %} |
4. Next, lets go to Asset folder, and also create another file, name it "featured-slider". Open the file and paste the code below.
.collection { padding: 5%; } slider-component { position: relative; display: block; } @media screen and (max-width: 989px) { .no-js slider-component .slider { padding-bottom: 3rem; } } .slider__slide { scroll-snap-align: start; flex-shrink: 0; } @media screen and (max-width: 749px) { .grid--col { width: 33%; } } @media screen and (max-width: 481px) { .grid--col { width: 50%; } } @media screen and (min-width: 750px) { .grid--col { width: 20%; } } .featured-title-wrapper { display: flex; align-items: center; justify-content: space-between; margin-bottom: 2rem; } .featured-title { margin: auto 0; } .featured-grid { display: flex; padding: 0; } .featured-grid li { list-style: none; } .slider.slider--tablet { position: relative; flex-wrap: inherit; overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth; scroll-padding-left: 1rem; -webkit-overflow-scrolling: touch; margin-bottom: 1rem; } .slider__slide { padding-bottom: 0; padding: 0 1rem; } @media (prefers-reduced-motion) { .slider--everywhere { scroll-behavior: auto; } } .slider.slider--everywhere .slider__slide { margin-bottom: 0; padding-bottom: 0; scroll-snap-align: center; } /* Scrollbar */ .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; display: flex; min-width: 2rem; justify-content: center; } @media screen and (max-width: 749px) { .slider-counter--dots, .slider-counter--numbers { margin: 0; } } @media screen and (max-width: 749px) { .slider-counter__link { padding: 0.7rem; } } .slider-counter__link--dots .dot { width: 1rem; height: 1rem; border-radius: 50%; border: 0.1rem solid rgba(var(--color-foreground), 0.5); padding: 0; display: block; } .slider-counter__link--active.slider-counter__link--dots .dot { background-color: rgb(var(--color-foreground)); } @media screen and (forced-colors: active) { .slider-counter__link--active.slider-counter__link--dots .dot { background-color: CanvasText; } } .slider-counter__link--dots:not(.slider-counter__link--active):hover .dot { border-color: rgb(var(--color-foreground)); } .slider-counter__link--dots .dot, .slider-counter__link--numbers { transition: transform 0.2s ease-in-out; } .slider-counter__link--active.slider-counter__link--numbers, .slider-counter__link--dots:not(.slider-counter__link--active):hover .dot, .slider-counter__link--numbers:hover { transform: scale(1.1); } .slider-counter__link--numbers { color: rgba(var(--color-foreground), 0.5); text-decoration: none; } .slider-counter__link--numbers:hover { color: rgb(var(--color-foreground)); } .slider-counter__link--active.slider-counter__link--numbers { text-decoration: underline; color: rgb(var(--color-foreground)); } .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; display: flex; align-items: center; justify-content: center; } .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); cursor: not-allowed; } .slider-button--next .icon { transform: rotate(-90deg); } .slider-button--prev .icon { transform: rotate(90deg); } .slider-button--next:not([disabled]):hover .icon { transform: rotate(-90deg) scale(1.1); } .slider-button--prev:not([disabled]):hover .icon { transform: rotate(90deg) scale(1.1); } .spaced-section--full-width:last-child featured-slideshow-component:not(.page-width) .slideshow__controls { border-bottom: none; } @media screen and (min-width: 750px) { .slideshow__controls { position: relative; } } slideshow-component:not(.page-width) .slider-buttons { border-right: 0; border-left: 0; } .slideshow__control-wrapper { display: flex; width: 30rem; overflow-x: auto; } .image--active { border: 5px solid var(--border-color); } .counter--mobile { display: none; } @media only screen and (max-width: 481px) { .counter--mobile { display: flex; } .slideshow__control-wrapper { display: none; } } .slider-counter__link { display: flex; align-items: center; justify-content: center; } .smallDot { width: 0.4rem !important; height: 0.4rem !important; } .mediumDot { width: 0.75rem !important; height: 0.75rem !important; } |
5. Lastly, in the same folder, go to the global.js or theme.js, then paste the code at the very bottom of the file.
class FeaturedSliderComponent extends HTMLElement { constructor() { super(); this.sliderControlWrapper = this.querySelector('.slider-buttons'); this.slider = this.querySelector('[id^="Slider-"]'); this.sliderItems = this.querySelectorAll('[id^="Slide-"]'); this.currentPageElement = this.querySelector('.slider-counter--current'); this.pageTotalElement = this.querySelector('.slider-counter--total'); this.prevButton = this.querySelector('button[name="previous"]'); this.nextButton = this.querySelector('button[name="next"]'); this.step = 0; this.sliderControlWrapper = this.querySelector('.slideshow__control-wrapper'); this.sliderControlLinksArray = Array.from(this.sliderControlWrapper.querySelectorAll('.slider-counter__link')); this.sliderControlLinksArray.forEach(link => link.addEventListener('click', this.linkToSlide.bind(this))); this.prevButton.addEventListener('click', this.onButtonClick.bind(this)); this.nextButton.addEventListener('click', this.onButtonClick.bind(this)); } update(slide) { this.sliderItems.forEach(image => { image.classList.remove('image--active'); image.removeAttribute('aria-current'); }); this.currentPageElement.innerHTML = slide + 1; this.pageTotalElement.innerHTML = this.sliderItems.length; this.sliderItems[slide].classList.add('image--active'); this.sliderItems[slide].setAttribute('aria-current', true); this.sliderControlButtons = this.querySelectorAll('.slider-counter__link'); this.sliderControlButtons.forEach(link => { link.classList.remove('slider-counter__link--active'); link.removeAttribute('aria-current'); }); this.sliderControlButtons[slide].classList.add('slider-counter__link--active'); this.sliderControlButtons[slide].setAttribute('aria-current', true); this.slideScrollPosition = slide * this.sliderItems[0].clientWidth; this.slider.scrollTo({ left: this.slideScrollPosition }); const controlWidth = this.querySelector(`[data-dot='${0}']`).clientWidth; const controlOffset = this.querySelector(`[data-dot='${slide}']`).offsetLeft; this.querySelector(`[data-dot='${slide}']`).scrollIntoView({block: "nearest", inline: "center"}); this.querySelectorAll(`.dot`).forEach(dot => dot.classList.remove('mediumDot')); this.querySelectorAll(`.dot`).forEach(dot => dot.classList.remove('smallDot')); if (controlOffset > controlWidth * 10){ if(slide > 4 && slide < this.sliderItems.length - 5) { this.querySelector(`[data-dot='${slide - 5}'] > .dot`).classList.add('smallDot'); this.querySelector(`[data-dot='${slide - 4}'] > .dot`).classList.add('mediumDot'); } } if (controlOffset < (controlWidth * 10) + (controlWidth * (this.sliderItems.length - 1)) ){ if(slide > 4 && slide < this.sliderItems.length - 5) { this.querySelector(`[data-dot='${slide + 4}'] > .dot`).classList.add('mediumDot'); this.querySelector(`[data-dot='${slide + 5}'] > .dot`).classList.add('smallDot'); } } } onButtonClick(event) { event.preventDefault(); if(event.currentTarget.name === 'next') { this.step++; if(this.step > this.sliderItems.length - 1) { this.step = 0 } } else { this.step--; if(this.step < 0) { this.step = this.sliderItems.length - 1 } } this.currentIndex(this.step); } linkToSlide(event) { const dotIndex = event.currentTarget.dataset.dot; this.step = dotIndex; this.currentIndex(this.step); } currentIndex(index) { this.update(index); } } customElements.define('featured-slider-component', FeaturedSliderComponent); |
Update 02/03/22: If you just installed a Dawn 2.5 and below theme then you might get an error but no need for major change. You just have to replace the step #2 with this code below.
{{ 'component-card.css' | asset_url | stylesheet_tag }} {{ 'component-price.css' | asset_url | stylesheet_tag }} {{ 'component-product-grid.css' | asset_url | stylesheet_tag }} {{ 'featured-slider.css' | asset_url | stylesheet_tag }} <link rel="stylesheet" href="{{ 'component-slider.css' | asset_url }}" media="print" onload="this.media='all'"> <link rel="stylesheet" href="{{ 'template-collection.css' | asset_url }}" media="print" onload="this.media='all'"> <noscript>{{ 'template-collection.css' | asset_url | stylesheet_tag }}</noscript> {%- liquid assign products_to_display = section.settings.collection.all_products_count assign swipe_on_mobile = true if section.settings.collection.all_products_count > section.settings.products_to_show assign products_to_display = section.settings.products_to_show assign more_in_collection = true endif -%} <div class="collection"> <div class="featured-title-wrapper{% if section.settings.title == blank %} title-wrapper-with-link--no-heading{% endif %}"> {% if section.settings.title != blank %} <h2 class="featured-title">{{ section.settings.title | escape }}</h2> {% endif %} {% if section.settings.show_view_all %} <a href="{{ section.settings.collection.url }}" class="button">{{ 'sections.featured_collection.view_all' | t }}</a> {% endif %} </div> <featured-slider-component style="--border-color: {{section.settings.border_color}};"> <ul id="Slider-{{ section.id }}" class="featured-grid product-grid {% if section.settings.collection.all_products_count > 2 and swipe_on_mobile and section.settings.products_to_show > 2 %} slider slider--tablet grid--peek{% endif %} {% if section.settings.show_view_all and section.settings.collection.products.size > section.settings.products_to_show %} negative-margin--small{% endif %}" role="list"> {%- for product in section.settings.collection.products limit: section.settings.products_to_show -%} <li id="Slide-{{ section.id }}-{{ forloop.index }}" data-image="{{forloop.index0}}" class="grid--col {% if section.settings.collection.all_products_count > 2 and swipe_on_mobile and section.settings.products_to_show > 2 %} slider__slide{% endif %}"> {% render 'product-card', product_card_product: product, media_size: section.settings.image_ratio, show_secondary_image: section.settings.show_secondary_image, add_image_padding: section.settings.add_image_padding, show_vendor: section.settings.show_vendor, show_image_outline: section.settings.show_image_outline, show_rating: section.settings.show_rating %} </li> {%- else -%} {%- for i in (1..4) -%} <li class="grid__item"> {% render 'product-card-placeholder' %} </li> {%- endfor -%} {%- endfor -%} </ul> {%- if section.settings.collection.all_products_count > 2 and swipe_on_mobile and section.settings.products_to_show > 2 -%} <div class="slideshow__controls slider-buttons no-js-hidden" style="display: flex"> <button type="button" class="slider-button slider-button--prev" data-step="1" name="previous" aria-label="{{ 'sections.slideshow.previous_slideshow' | t }}" aria-controls="Slider-{{ section.id }}">{% render 'icon-caret' %}</button> <div class="slider-counter slider-counter--{{ section.settings.slider_visual }}{% if section.settings.slider_visual == 'numbers' %} caption{% endif %}"> <div class="counter--mobile"> <span class="slider-counter--current">1</span> <span aria-hidden="true"> / </span> <span class="slider-counter--total"> {% if section.settings.products_to_show < section.settings.collection.products %} {{section.settings.products_to_show }} {% else %} {{section.settings.collection.all_products_count}} {% endif %} </span> </div> <div class="slideshow__control-wrapper slider"> {%- for product in section.settings.collection.products limit: section.settings.products_to_show -%} <button class="slider-counter__link slider-counter__link--{{ section.settings.slider_visual }} link" data-dot="{{forloop.index0}}" style="padding: 1rem; width: 100%" aria-label="{{ 'sections.slideshow.load_slide' | t }} {{ forloop.index }} {{ 'general.slider.of' | t }} {{ forloop.length}}" aria-controls="Slider-{{ section.id }}"> {%- if section.settings.slider_visual == 'numbers' -%}{{ forloop.index }}{% else %}<span class="dot"></span>{%- endif -%} </button> {%- endfor -%} </div> </div> <button type="button" class="slider-button slider-button--next" name="next" data-step="1" aria-label="{{ 'sections.slideshow.next_slideshow' | t }}" aria-controls="Slider-{{ section.id }}">{% render 'icon-caret' %}</button> </div> <noscript> <div class="slider-buttons" style="display: flex"> <div class="slider-counter"> {%- for product in section.settings.collection.products limit: section.settings.products_to_show -%} <a href="#Slide-{{ section.id }}-{{ forloop.index }}" data-dot="{{forloop.index}}" class="slider-counter__link link" aria-label="{{ 'sections.slideshow.load_slide' | t }} {{ forloop.index }} {{ 'general.slider.of' | t }} {{ forloop.length}}"> {{ forloop.index }} </a> {%- endfor -%} </div> </div> </noscript> {%- endif -%} </featured-slider-component> </div> {% schema %} { "name": "Featured Slider", "tag": "section", "class": "spaced-section", "settings": [ { "type": "text", "id": "title", "default": "Featured collection", "label": "t:sections.featured-collection.settings.title.label" }, { "type": "collection", "id": "collection", "label": "t:sections.featured-collection.settings.collection.label" }, { "type": "range", "id": "products_to_show", "min": 2, "max": 99, "step": 1, "default": 4, "label": "t:sections.featured-collection.settings.products_to_show.label" }, { "type": "checkbox", "id": "show_view_all", "default": true, "label": "t:sections.featured-collection.settings.show_view_all.label" }, { "type": "header", "content": "t:sections.featured-collection.settings.header.content" }, { "type": "select", "id": "image_ratio", "options": [ { "value": "adapt", "label": "t:sections.featured-collection.settings.image_ratio.options__1.label" }, { "value": "portrait", "label": "t:sections.featured-collection.settings.image_ratio.options__2.label" }, { "value": "square", "label": "t:sections.featured-collection.settings.image_ratio.options__3.label" } ], "default": "adapt", "label": "t:sections.featured-collection.settings.image_ratio.label" }, { "type": "checkbox", "id": "show_secondary_image", "default": false, "label": "t:sections.featured-collection.settings.show_secondary_image.label" }, { "type": "checkbox", "id": "add_image_padding", "default": false, "label": "t:sections.featured-collection.settings.add_image_padding.label" }, { "type": "checkbox", "id": "show_image_outline", "default": true, "label": "t:sections.featured-collection.settings.show_image_outline.label" }, { "type": "checkbox", "id": "show_vendor", "default": false, "label": "t:sections.featured-collection.settings.show_vendor.label" }, { "type": "checkbox", "id": "show_rating", "default": false, "label": "t:sections.featured-collection.settings.show_rating.label", "info": "t:sections.featured-collection.settings.show_rating.info" }, { "type": "color", "id": "border_color", "label": "border color", "default": "#eee" }, { "type": "select", "id": "slider_visual", "options": [ { "value": "dots", "label": "dots" }, { "value": "numbers", "label": "numbers" } ], "default": "numbers", "label": "numbers" } ], "presets": [ { "name": "Featured Collection Slider" } ] } {% endschema %} |
That's it. Only good 5 steps.
4 comments
Hi. thank you so much. i am not sure why they dont have collection slider in dawn. this works great
Hi @FATIMA BIN SUMAIT,
Please refresh your browser
The code doesnt display properly, I am logged on but still not able to access only this code I can see the other tutorials
The updated code works perfectly. I really like this feature. Thank you!