Compatibility: Compatible with theme version 2.5 and Shopify 2.0 FREE themes
Showcase your blogs with a slider. The style adjust to whatever Shopify 3.0 theme you have.
Check DEMO store here 💻. Password: made4uo
What you are buying:
- Add a blog list slider
What makes our code better:
- We do not use external libraries, with that being said, our code will have no to minimal effect to your website's speed performance
- We do not leave or add codes use to advertise for our website
- Our code is mobile friendly
To Start:
1. Go to Admin Shopify store > Themes > Actions > Edit Code
2. In Section folder, create a new section, name it whatever you want, then replace the default code with the code below.
{{ 'component-product-grid.css' | asset_url | stylesheet_tag }} {{ 'blog-slider.css' | asset_url | stylesheet_tag }} <link rel="stylesheet" href="{{ 'template-collection.css' | asset_url }}" media="print" onload="this.media='all'"> <noscript>{{ 'template-collection.css' | asset_url | stylesheet_tag }}</noscript> <div class="blogSlider" style= "padding-top: {{ section.settings.padding_top | append: "%" }}; padding-bottom: {{section.settings.padding_bottom | append: "%" }}"> <div class="blogTitleWrapper{% if section.settings.title == blank %} title-wrapper-with-link--no-heading{% endif %}"> {% if section.settings.title != blank %} <h2 class="blogTitle">{{ section.settings.title | escape }}</h2> {% endif %} {% if section.settings.show_view_all %} <a href="{{section.settings.blog.handle | prepend: "/blogs/" }}" class="button">View All</a> {% endif %} </div> <universal-slider-component style="--border-color: {{section.settings.border_color}};"> {% if section.settings.slider_visual == 'slider' %} <div class="sliderCounterBox"> <button type="button" class="sliderCounterButton sliderCounterBtn--prev slider-button {% if section.settings.slider_button_fixed != true%}slider_button_fixed{% endif %}" 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 class="product-grid slider slider--tablet" role="list"> {%- for article in section.settings.blog.articles -%} {% assign block_length = forloop.length %} <li class="collection-list__item grid__item grid--col{% if section.settings.swipe_on_mobile %} slider__slide{% endif %}" {{ block.shopify_attributes }}> {%- render 'article-card', article: article, media_aspect_ratio: article.image.aspect_ratio, show_image: section.settings.show_image, show_date: section.settings.show_date, show_author: section.settings.show_author, show_excerpt: true -%} <style> .blogSlider .card-wrapper { background: {{ section.settings.background}}; } </style> </li> {%- endfor -%} </ul> {% if section.settings.slider_visual == 'slider' %} <button type="button" class="sliderCounterButton sliderCounterBtn--next slider-button {% if section.settings.slider_button_fixed != true %}slider_button_fixed{% 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 block_length > 3 -%} {%- if section.settings.slider_visual == 'slider' -%} <div class="sliderContainer"> <input type="range" min="0" max="{{block_length | minus: 1 }}" value="1" class="sliderCounter" id="myRange"> </div> <style> .blogSlider .sliderCounter::-webkit-slider-thumb { width: calc(100% / {{block_length}}); } .blogSlider .sliderCounter::-moz-range-thumb { width: calc(100% / {{block_length}}); } </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"> {{block_length}} </span> </div> <div class="slideshow__control-wrapper slider"> {%- for article in section.settings.blog.articles-%} <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 article in section.settings.blog.articles-%} <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 -%} </universal-slider-component> </div> {% schema %} { "name": "Blog List Slider", "tag": "section", "class": "spaced-section", "settings": [ { "type": "text", "id": "title", "default": "Blog List", "label": "Title" }, { "type": "blog", "id": "blog", "label": "Blog" }, { "type": "checkbox", "id": "show_image", "default": true, "label": "Show featured image" }, { "type": "checkbox", "id": "show_date", "default": true, "label": "Show date" }, { "type": "checkbox", "id": "show_author", "default": false, "label": "Show author" }, { "type": "checkbox", "id": "show_view_all", "default": true, "label": "View all button" }, { "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": "Blog card" }, { "type": "color", "id": "background", "label": "Card background", "default": "#eee" }, { "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": "Counter" }, { "type": "checkbox", "id": "slider_button_fixed", "default": true, "label": "Slider button fixed" } ], "presets": [ { "name": "Blog List Slider" } ] } {% endschema %} |
3. Let's create a stylesheet. Go to Asset folder and create a css file, name it "blog-slider." Then paste the code below.
.blogSlider { padding: 5%; overflow: hidden; } .blogSlider universal-slider-component { position: relative; display: block; } .blogSlider .card__information { padding: 1.7rem 1rem !important; } .blogSlider .card__heading { text-align: center; } @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 (min-width: 750px) { .blogSlider .grid--col { width: 33%; } } @media screen and (max-width: 749px) { .blogSlider .grid--col { width: 50%; } } @media screen and (max-width: 481px) { .blogSlider .grid--col { min-width: 100%; width: 100%; } } .blogSlider .blogTitleWrapper { display: flex; align-items: center; justify-content: space-between; margin-bottom: 2rem; } .blogSlider .blogTitle { margin: auto 0; } .blogSlider .featured-grid { display: flex; padding: 0; } .blogSlider .featured-grid li { list-style: none; } .blogSlider li { list-style: none; } .blogSlider .slider--tablet { display: flex; 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; } .blogSlider .collection-list__item { padding: 1.5rem; } .blogSlider .slider__slide { padding-bottom: 0; padding: 0 1rem; } @media (prefers-reduced-motion) { .slider--everywhere { scroll-behavior: auto; } } .blogSlider .slider.slider--everywhere .slider__slide { margin-bottom: 0; padding-bottom: 0; scroll-snap-align: center; } .blogSlider .slider { scrollbar-color: rgb(var(--color-foreground)) rgba(var(--color-foreground), 0.04); -ms-overflow-style: none; scrollbar-width: none; } .blogSlider .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; } .blogSlider .slider::-webkit-scrollbar-thumb { background-color: rgb(var(--color-foreground)); border-radius: 0.4rem; border: 0; } .blogSlider .slider::-webkit-scrollbar-track { background: rgba(var(--color-foreground), 0.04); border-radius: 0.4rem; } .blogSlider .slider-counter { margin: 0 1.2rem; display: flex; min-width: 2rem; justify-content: center; } @media screen and (max-width: 749px) { .blogSlider .slider-counter--dots, .blogSlider .slider-counter--numbers { margin: 0; } } @media screen and (max-width: 749px) { .blogSlider .slider-counter__link { padding: 0.7rem; } } .blogSlider .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; } .blogSlider .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); } .blogSlider .slider-counter__link--numbers { color: rgba(var(--color-foreground), 0.5); text-decoration: none; } .blogSlider .slider-counter__link--numbers:hover { color: rgb(var(--color-foreground)); } .blogSlider .slider-counter__link--active.slider-counter__link--numbers { text-decoration: underline; color: rgb(var(--color-foreground)); } .blogSlider .slider-buttons { display: flex; align-items: center; justify-content: center; } .blogSlider .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) { .blogSlider .slideshow__controls { position: relative; } .slider--tablet.grid--peek .grid__item { width: 25%; } } slideshow-component:not(.page-width) .slider-buttons { border-right: 0; border-left: 0; } .blogSlider .slideshow__control-wrapper { display: flex; width: 28rem; overflow-x: auto; } .image--active { border: 5px solid var(--border-color); } .counter--mobile { display: none; } @media only screen and (max-width: 481px) { .blogSlider .counter--mobile { display: flex; } .blogSlider .slideshow__control-wrapper { display: none; } } .blogSlider .slider-counter__link { display: flex; align-items: center; justify-content: center; } .blogSlider .smallDot { width: 0.4rem !important; height: 0.4rem !important; } .blogSlider .mediumDot { width: 0.75rem !important; height: 0.75rem !important; } .blogSlider .slidecontainer { width: 100%; } .blogSlider .sliderCounter { -webkit-appearance: none; width: 100%; height: 5px; border-radius: 5px; background: #d3d3d3; outline: none; opacity: 0.7; -webkit-transition: 0.2s; transition: opacity 0.2s; } .sliderCounter:hover { opacity: 1; } .sliderCounter::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; height: 5px; margin: 10px 0; border-radius: 5px; background: black; cursor: pointer; } .sliderCounter::-moz-range-thumb { height: 5px; padding: 5px; margin: 10px 0; border-radius: 5px; background: black; cursor: pointer; } .sliderCounterBox { display: flex; align-items: center; } .sliderCounterButton { display: none; position: absolute; background: black !important; color: white !important; transition: all 0.2s ease; z-index: 10; } .blogSlider:hover .sliderCounterBtn--prev { left: -50px; } .blogSlider:hover .sliderCounterBtn--next { right: -50px; } .sliderCounterBtn--prev > svg { transform: rotate(90deg); } .slider_button_fixed.sliderCounterBtn--prev { left: -100px; } .slider_button_fixed.sliderCounterBtn--next { right: -100px; } .sliderCounterBtn--prev { left: -50px; } .sliderCounterBtn--next { right: -50px; } .sliderCounterBtn--next > svg { transform: rotate(-90deg); } .sliderCounterButton:hover { transform: scale(1.1); } .sliderCounterButton > svg { height: 2rem !important; } @media screen and (max-width: 749px) { .sliderCounterBtn--prev { left: 0; } .sliderCounterBtn--next { right: 0; } } |
4. Last thing to do is add a javascript code for slider to work. Go to global.js file under the Asset folder, and paste the code below.
NOTE: If you bought the collection-list-slider, you might have this code. If so, skip this part.
class UniversalSliderComponent extends HTMLElement { constructor() { super(); this.sliderControlWrapper = this.querySelector(".slider-buttons"); this.slider = this.querySelector("ul"); this.sliderItems = this.querySelectorAll("li"); 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(".sliderCounterBtn--prev"); this.sliderButtonNext = this.querySelector(".sliderCounterBtn--next"); this.step = 0; this.sliderControlWrapper = this.querySelector( ".slideshow__control-wrapper" ); this.sliderControlLinksArray = Array.from( this.sliderControlWrapper.querySelectorAll(".slider-counter__link") ); this.sliderControlLinksArray.forEach((t) => t.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(t) { this.sliderItems.forEach((t) => { t.classList.remove("image--active"); t.removeAttribute("aria-current"); }); this.currentPageElement.innerHTML = t + 1; this.pageTotalElement.innerHTML = this.sliderItems.length; this.sliderItems[t].classList.add("image--active"); this.sliderItems[t].setAttribute("aria-current", true); this.sliderControlButtons = this.querySelectorAll(".slider-counter__link"); this.sliderControlButtons.forEach((t) => { t.classList.remove("slider-counter__link--active"); t.removeAttribute("aria-current"); }); this.sliderControlButtons[t].classList.add("slider-counter__link--active"); this.sliderControlButtons[t].setAttribute("aria-current", true); this.slideScrollPosition = t * this.sliderItems[0].clientWidth; this.slider.scrollTo({ left: this.slideScrollPosition }); if (this.sliderCounter) { this.sliderCounter.value = t; } if (this.querySelector(".dot")) { const e = this.querySelector(`[data-dot='${0}']`).clientWidth; const s = this.querySelector(`[data-dot='${t}']`).offsetLeft; this.querySelector(`[data-dot='${t}']`).scrollIntoView({ block: "nearest", inline: "center", }); this.querySelectorAll(`.dot`).forEach((t) => t.classList.remove("mediumDot") ); this.querySelectorAll(`.dot`).forEach((t) => t.classList.remove("smallDot") ); if (s > e * 10) { if (t > 4 && t < this.sliderItems.length - 5) { this.querySelector(`[data-dot='${t - 5}'] > .dot`).classList.add( "smallDot" ); this.querySelector(`[data-dot='${t - 4}'] > .dot`).classList.add( "mediumDot" ); } } if (s < e * 10 + e * (this.sliderItems.length - 1)) { if (t > 4 && t < this.sliderItems.length - 5) { this.querySelector(`[data-dot='${t + 4}'] > .dot`).classList.add( "mediumDot" ); this.querySelector(`[data-dot='${t + 5}'] > .dot`).classList.add( "smallDot" ); } } } } onButtonClick(t) { t.preventDefault(); if (t.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(t) { const e = t.currentTarget.dataset.dot; this.step = e; this.currentIndex(this.step); } currentIndex(t) { this.update(t); } sliderCounterUpdate(t) { t.preventDefault(); this.step = this.sliderCounter.value; this.currentIndex(this.step); } } customElements.define("universal-slider-component", UniversalSliderComponent); |