How To Add Vertical Card Slider In Shopify – [GSAP Animation]

Today, I’ll show you how to add a vertical card slider to your Shopify store using GSAP animations. It’s a quick and simple process where I’ll provide all the code you need—you just have to copy and paste it. No advanced coding knowledge required! This slider is perfect for making your Shopify store more interactive and engaging for your visitors. I’ll guide you step-by-step. So, stick around, and let’s get started!

Animated Vertical Card Slider for Shopify

Create a new section “featured-cards-slider.liquid” with the following code:

{% schema %}
{
"name": "Featured Cards Slider",
"settings": [
{
"type": "color",
"id": "background_color",
"label": "Background Color",
"default": "#dfe1c8"
},
{
"type": "color",
"id": "button_color",
"label": "Button Color",
"default": "#ffffff"
},
{
"type": "color",
"id": "button_text_color",
"label": "Button Text Color",
"default": "#000000"
},
{
"type": "checkbox",
"id": "enable_button",
"label": "Enable Button",
"default": true
}
],
"blocks": [
{
"type": "slide",
"name": "Slide",
"limit": 5,
"settings": [
{
"type": "image_picker",
"id": "slide_image",
"label": "Slide Image"
},
{
"type": "text",
"id": "slide_heading",
"label": "Slide Heading",
"default": "Lorem ipsum"
},
{
"type": "text",
"id": "button_text",
"label": "Button Text",
"default": "Shop Now"
},
{
"type": "url",
"id": "button_link",
"label": "Button Link"
}
]
}
],
"presets": [
{
"name": "Featured Cards Slider",
"blocks": [
{
"type": "slide"
},
{
"type": "slide"
},
{
"type": "slide"
}
]
}
]
}
{% endschema %}

<div class="featured-cards-container">
<div class="featured-cards-slider">
{% for block in section.blocks %}
<div class="featured-card" {{ block.shopify_attributes }}>
{% if block.settings.slide_image %}
{{ block.settings.slide_image | image_url: width: 2000 | image_tag }}
{% endif %}
<div class="card-copy">
<h1>{{ block.settings.slide_heading }}</h1>
{% if block.settings.button_link and section.settings.enable_button %}
<div class="card-button-wrapper">
<a href="{{ block.settings.button_link }}" class="card-button">
{{ block.settings.button_text }}
</a>
</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>

<style>
.featured-cards-container {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
background-color: {{ section.settings.background_color }};
}

.featured-cards-slider {
position: absolute;
top: 15vh;
width: 100vw;
height: 100vh;
overflow: hidden;
perspective: 300px;
perspective-origin: 50% 50%;
}

.featured-card {
position: absolute;
top: 35%;
left: 50%;
width: 50%;
height: 400px;
border-radius: 10px;
overflow: hidden;
transform: translate3d(-50%, -50%, 0);
background-color: #000;
opacity: 1;
visibility: visible;
cursor: pointer;
}

.featured-card img {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
opacity: 0.75;
}

.card-copy {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%);
text-align: center;
}

.card-copy h1 {
position: relative;
text-align: center;
font-size: 6vw;
font-weight: 300;
letter-spacing: -0.05em;
text-transform: uppercase;
color: #dfe1c8;
margin-bottom: 20px;
}

.card-copy h1 span {
position: relative;
display: inline-block;
opacity: 1;
visibility: visible;
}

.card-button-wrapper {
position: relative;
margin-top: 40px;
opacity: 1; /* Always visible */
transform: translateY(0); /* No animation */
}

.card-button {
display: inline-block;
padding: 12px 30px;
background-color: {{ section.settings.button_color }};
color: {{ section.settings.button_text_color }};
text-decoration: none;
border-radius: 25px;
font-size: 16px;
font-weight: 500;
transition: all 0.3s ease;
border: 2px solid transparent;
}

@media(max-width: 500px) {
.featured-cards-slider {
top: 27vh;
}
.featured-card {
height: 300px;
width: 80%;
}
.card-copy h1 {
font-size: 8vw;
}
.card-button {
padding: 10px 20px;
font-size: 14px;
}
.card-button-wrapper {
margin-top: 30px;
}
}
</style>

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/CustomEase.min.js" defer></script>

<script defer>
document.addEventListener('DOMContentLoaded', function() {
setTimeout(initializeSlider, 100);
});

function initializeSlider() {
if (typeof gsap === 'undefined' || typeof CustomEase === 'undefined') {
setTimeout(initializeSlider, 100);
return;
}

CustomEase.create("cubic", "0.83, 0, 0.17, 1");

let isAnimating = false;

function splitTextIntoSpans() {
const headings = document.querySelectorAll('.card-copy h1');
headings.forEach(heading => {
if (!heading.querySelector('span')) {
const text = heading.textContent;
heading.innerHTML = text.split('').map(char =>
`<span>${char === ' ' ? '&nbsp;&nbsp;' : char}</span>`
).join('');
}
});
}

function initializeCards() {
const cards = Array.from(document.querySelectorAll('.featured-card'));

cards.forEach(card => {
card.style.visibility = 'visible';
card.style.opacity = '1';
});

gsap.to(cards, {
y: (i) => -15 + 15 * i + '%',
z: (i) => 15 * i,
duration: 1,
ease: 'cubic',
stagger: -0.1,
clearProps: 'visibility,opacity'
});
}

function handleCardAnimation(event) {
// Don't trigger animation if clicking the button
if (event.target.closest('.card-button')) {
return;
}

if (isAnimating) return;
isAnimating = true;

const slider = document.querySelector('.featured-cards-slider');
const cards = Array.from(slider.querySelectorAll('.featured-card'));
const lastCard = cards.pop();
const nextCard = cards[cards.length - 1];

gsap.to(lastCard.querySelectorAll('.card-copy h1 span'), {
y: 200,
duration: 0.75,
ease: 'cubic'
});

gsap.to(lastCard, {
y: '+=150%',
duration: 0.75,
ease: 'cubic',
onComplete: () => {
slider.prepend(lastCard);
initializeCards();
gsap.set(lastCard.querySelectorAll('.card-copy h1 span'), { y: -200 });
setTimeout(() => {
isAnimating = false;
}, 1000);
}
});

gsap.to(nextCard.querySelectorAll('.card-copy h1 span'), {
y: 0,
duration: 1,
ease: 'cubic',
stagger: 0.05
});
}

splitTextIntoSpans();

gsap.set('.card-copy h1 span', { y: -200 });
gsap.set('.featured-cards-slider .featured-card:last-child .card-copy h1 span', { y: 0 });

setTimeout(initializeCards, 100);

const cards = document.querySelectorAll('.featured-card');
cards.forEach(card => {
card.addEventListener('click', handleCardAnimation);
});
}
</script>
5/5 - (6 votes)

About

Leave a Comment

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