Compatability: Dawn 2.0 to Shopify FREE themes.
I created a Collection with numbers and dots (see version here). This time I added a clickable slider option. Please see the checkbox in the section setting and check for the corresponding version.
NOTE: The quick-view button in the demo is a separate code. Check this link for quick-view button.
Check DEMO store here 💻. Password: made4uo
I have a checkbox available in the theme editor to convert the code to newer or older version of Shopify Dawn Theme.
To Start:
1. Go to Admin Shopify store > Themes > Actions > Edit Code
2. In Section folder, create a new section, name it "Collection Slider", then replace the default code with 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="collectionSlider" style= "padding-top: {{ section.settings.padding_top | append: "&" }}; padding-bottom: {{section.settings.padding_bottom | append: "&" }}"> <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> <collection-slider-component style="--border-color: {{section.settings.border_color}};"> {% if section.settings.slider_visual == 'slider' %}<div class="sliderCounterBox"> <button type="button" class="sliderCounterButton sliderCounterButton--prev slider-button" data-step="1" name="previous" aria-label="{{ 'sections.slideshow.previous_slideshow' | t }}" style"display: flex" aria-controls="Slider-{{ section.id }}">{% render 'icon-caret' %}</button> {% endif %} <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 %}"> {% if section.settings.newer_version %} {% 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 %} {% else %} {% 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 %} {% endif %} </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.slider_visual == 'slider' %} <button type="button" class="sliderCounterButton sliderCounterButton--next slider-button {% if section.settings.slider_visual != 'slider' %}hidden {% endif %}" name="next" data-step="1" style="display: flex" aria-label="{{ 'sections.slideshow.next_slideshow' | t }}" aria-controls="Slider-{{ section.id }}">{% render 'icon-caret' %} </button> </div> {% endif %} {%- if section.settings.collection.all_products_count > 2 and swipe_on_mobile and section.settings.products_to_show > 2 -%} {%- if section.settings.slider_visual == 'slider' -%} <div class="sliderContainer"> <input type="range" min="0" max="{{products_to_display | minus: 1}}" value="1" class="sliderCounter" id="myRange"> </div> <style> .collectionSlider .sliderCounter::-webkit-slider-thumb { width: calc(100% / {{products_to_display }}); } .collectionSlider .sliderCounter::-moz-range-thumb { width: calc(100% / {{products_to_display}}); } </style> {% endif %} <div class="slideshow__controls slider-buttons no-js-hidden {% if section.settings.slider_visual == 'slider' %}hidden {% endif %}" 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 -%} </collection-slider-component> </div> {% schema %} { "name": "Collection Slider", "tag": "section", "class": "spaced-section", "settings": [ { "type": "checkbox", "id": "newer_version", "default": true, "label": "Dawn version 2.6 and above" }, { "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": "Additional Section padding" }, { "type": "range", "id": "padding_top", "min": 0, "max": 99, "step": 1, "unit": "%", "default": 0, "label": "Section padding top" }, { "type": "range", "id": "padding_bottom", "min": 0, "max": 99, "step": 1, "unit": "%", "default": 0, "label": "Section padding bottom" }, { "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" }, { "value": "slider", "label": "slider" } ], "default": "numbers", "label": "numbers" } ], "presets": [ { "name": "Collection Slider" } ] } {% endschema %} |
3. Next, we need to add some beauty to it. Open the Asset folder, and "create a new asset." Name it "collection-slider." Then place the code below.
.collectionSlider { |
4. Last thing to do is to add the brain in our section. Still at the Asset folder, open the global.js and add the code below.
class CollectionSliderComponent extends HTMLElement { constructor() { super(); this.sliderControlWrapper = this.querySelector('.slider-buttons'); this.slider = this.querySelector('[id^="Slider-"]'); this.sliderItems = this.querySelectorAll('[id^="Slide-"]'); this.sliderCounter = this.querySelector('.sliderCounter'); this.currentPageElement = this.querySelector('.slider-counter--current'); this.pageTotalElement = this.querySelector('.slider-counter--total'); this.prevButton = this.querySelector('.slider-button--prev'); this.nextButton = this.querySelector('.slider-button--next'); this.sliderButtonPrev = this.querySelector('.sliderCounterButton--prev'); this.sliderButtonNext = this.querySelector('.sliderCounterButton--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)); if(this.sliderCounter) { this.sliderButtonPrev.addEventListener('click', this.onButtonClick.bind(this)); this.sliderButtonNext.addEventListener('click', this.onButtonClick.bind(this)); this.sliderCounter.addEventListener('change', this.sliderCounterUpdate.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 }); if(this.sliderCounter) { this.sliderCounter.value = slide; } if(this.querySelector('.dot')) { 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); } sliderCounterUpdate(event) { event.preventDefault(); this.step = this.sliderCounter.value; this.currentIndex(this.step); } } customElements.define('collection-slider-component', CollectionSliderComponent); |
That's it. Enjoy (",)