Skip to content

Instantly share code, notes, and snippets.

@olh
Created November 5, 2021 15:19
Show Gist options
  • Select an option

  • Save olh/18497838738c8cdb6c8b60c17bce1a95 to your computer and use it in GitHub Desktop.

Select an option

Save olh/18497838738c8cdb6c8b60c17bce1a95 to your computer and use it in GitHub Desktop.
Splide - linked product cards
<section class="carousel" aria-label="carousel with product cards">
<p class="sr-only">This is a carousel with rotating cards. Use the previous and next buttons to navigate, and Enter to activate cards.</p>
<!-- Previous button -->
<div class="arrow-wrapper previous-button-wrapper">
<button class="previous-button is-control">
<span class="fas fa-angle-left" aria-hidden="true"></span>
<span class="sr-only">Previous cards</span>
</button>
</div>
<!-- Slide content -->
<div class="splide">
<div class="splide__track">
<div class="splide__list">
<div class="card splide__slide" role="group" aria-label="card 1 of 7">
<a href="https://www.alffredo.com.br/" target="_blank">
<div class="image">
<img src="https://static.wixstatic.com/media/c5a9d1_bc2b261b88894f419d6dc0847062a9e1~mv2.png/v1/fill/w_232,h_232,usm_1.20_1.00_0.01/file.webp" class="product-image" alt="">
</div>
<h2 class="title">ALCATRA LIMPO
</h2>
</a>
<div class="content">
<p>Em qualquer gramagem.</p>
<div class="price">
<!-- add "now"? -->
<span class="new-price">R$ 53,98</span>
<span class="original-price">
por kg.
</div>
</div>
</div>
<div class="card splide__slide" role="group" aria-label="card 2 of 7">
<a href="https://www.alffredo.com.br/" target="_blank">
<div class="image">
<img src="https://static.wixstatic.com/media/c5a9d1_ee2dc255136443c0ac19cf24a8e199fd~mv2.jpg/v1/fill/w_232,h_232,usm_1.20_1.00_0.01/file.webp" class="product-image" alt="">
</div>
<h2 class="title">ASSADO EM TIRAS 1953
</h2>
</a>
<div class="content">
<p>Traseiro. Também pode ser vendido em janelas.
</p>
<div class="price">
<!-- add "now"? -->
<span class="new-price">R$ 54,98</span>
<span class="original-price">
por kg.
</div>
</div>
</div>
<div class="card splide__slide" role="group" aria-label="card 3 of 7">
<a href="https://www.alffredo.com.br/" target="_blank">
<div class="image">
<img src="https://static.wixstatic.com/media/c5a9d1_7c2463e638e2444f823beaeb04eb1143~mv2.png/v1/fill/w_232,h_232,usm_1.20_1.00_0.01/file.webp" class="product-image" alt="">
</div>
<h2 class="title">BIFE DE ALCATRA 100g
</h2>
</a>
<div class="content">
<p>Em qualquer gramagem.</p>
<div class="price">
<!-- add "now"? -->
<span class="new-price">R$ 54,98</span>
<span class="original-price">
por kg.
</div>
</div>
</div>
<div class="card splide__slide" role="group" aria-label="card 4 of 7">
<a href="https://www.alffredo.com.br/" target="_blank">
<div class="image">
<img src="https://static.wixstatic.com/media/c5a9d1_bf9ecc1d7d3d41a6b9a942126cec3a7d~mv2.png/v1/fill/w_232,h_232,usm_1.20_1.00_0.01/file.webp​ " class="product-image" alt="">
</div>
<h2 class="title">BIFE DE COXÃO DE FORA
</h2>
</a>
<div class="content">
<p>Em qualquer gramagem.</p>
<div class="price">
<!-- add "now"? -->
<span class="new-price">R$ 41,98</span>
<span class="original-price">
por kg.
</div>
</div>
</div>
<div class="card splide__slide" role="group" aria-label="card 5 of 7">
<a href="https://www.alffredo.com.br/" target="_blank">
<div class="image">
<img src="https://static.wixstatic.com/media/c5a9d1_aef8c8a3c445434c849aa8237789fcd8~mv2.jpg/v1/fill/w_232,h_232,usm_1.20_1.00_0.01/file.webp" class="product-image" alt="">
</div>
<h2 class="title">BISTECA DE ENTRECOT (PRIME RIB)
</h2>
</a>
<div class="content">
<p>Em qualquer gramagem.</p>
<div class="price">
<!-- add "now"? -->
<span class="new-price">R$ 56,98</span>
<span class="original-price">
por kg.
</div>
</div>
</div>
<div class="card splide__slide" role="group" aria-label="card 6 of 7">
<a href="https://www.alffredo.com.br/" target="_blank">
<div class="image">
<img src="https://static.wixstatic.com/media/c5a9d1_578a24147a1f4137a1bda68ae641c3db~mv2.png/v1/fill/w_232,h_232,usm_1.20_1.00_0.01/file.webp" class="product-image" alt="">
</div>
<h2 class="title">FILÉ MIGNON CORTE INTEIRO
</h2>
</a>
<div class="content">
<p>Limpo sem cordão. Preço por kg.</p>
<div class="price">
<!-- add "now"? -->
<span class="new-price">R$ 72,98</span>
<span class="original-price">
por kg.
</div>
</div>
</div>
<div class="card splide__slide" role="group" aria-label="card 7 of 7">
<a href="https://www.alffredo.com.br/" target="_blank">
<div class="image">
<img src="https://static.wixstatic.com/media/c5a9d1_6738f8c0e366438eb7af83ea33ffc928~mv2.jpg/v1/fill/w_232,h_232,usm_1.20_1.00_0.01/file.webp" class="product-image" alt="">
</div>
<h2 class="title">BIFE ANCHO
</h2>
</a>
<div class="content">
<p>Em qualquer gramagem.</p>
<div class="price">
<!-- add "now"? -->
<span class="new-price">R$ 55,98</span>
<span class="original-price">
por kg.
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Next button -->
<div class="arrow-wrapper next-button-wrapper">
<button class="next-button is-control">
<span class="fas fa-angle-right" aria-hidden="true"></span>
<span class="sr-only">Next cards</span>
</button>
</div>
</section>
var splide;
var previousButton, nextButton;
document.addEventListener('DOMContentLoaded', function() {
previousButton = document.querySelector('.carousel .previous-button');
nextButton = document.querySelector('.carousel .next-button');
splide = new Splide('.splide', {
gap: '15px',
padding: {
left: '50px',
right: '50px'
},
arrows: false,
perPage: 3,
type: 'loop',
pagination: false,
keyboard: false, // Splide listens to key events at the document level and moves ALL carousels when arrow keys are used. Also, keyboard controls are not expected by real users.
slideFocus: false, // removes tabindex="0" from each slide wrapper, since we only want our links inside each slide to receive focus.
breakpoints: {
575: {
perPage: 2
},
375: {
perPage: 1
}
}
}).mount();
// To prevent animation issues, let's make every slide visible before a transition happens. Splide will then automatically remove the `.is-visible` class from non-visible slides once the transition is finished.
splide.on('move', function() {
var slides = document.querySelectorAll('.splide .splide__slide');
slides.forEach(function(slide) {
slide.classList.add('is-visible');
});
});
// Go to the previous slide when the Previous button is activated
previousButton.addEventListener('click', function(e) {
splide.go('<');
});
// Go to the next slide when the Next button is activated
nextButton.addEventListener('click', function(e) {
splide.go('>');
});
});
<script src="https://cdn.jsdelivr.net/npm/@splidejs/splide@latest/dist/js/splide.min.js"></script>

Splide - linked product cards

A responsive product card carousel built with Splide, using accessibility improvements crafted by expert accessibility specialists at Accessible360.

A Pen by olh on CodePen.

License.

/**
Setup for code demo only
*/
:root {
--carousel-height: 240px;
}
body {
margin: 10px;
}
/**
Container
*/
.carousel {
position: relative;
max-width: 100%;
}
/**
Controls (previous/next buttons)
*/
.arrow-wrapper {
position: absolute;
top: 0;
height: 100%;
z-index: 1;
display: flex;
align-items: center;
background-color: white;
}
.previous-button-wrapper { left: 0; }
.next-button-wrapper { right: 0; }
.is-control {
background: 0;
border: 0;
padding: 0 10px;
z-index: 1;
cursor: pointer;
font-size: 40px;
color: rgba(0,0,0,.6);
transition: all .2s linear;
}
.is-control:hover {
color: rgba(0,0,0,1);
}
.is-control:focus {
outline: none;
background-color: rgba(0,0,0,.8);
color: rgba(255,255,255,1);
border-radius: 5px;
}
/**
Single card
*/
.card {
position: relative;
overflow: hidden;
border-radius: 3px;
border: 1px solid rgba(0,0,0,.2);
text-decoration: none;
color: rgba(0,0,0,.9);
cursor: pointer;
transition: all .1s linear;
max-width: 200px;
}
.card a {
text-decoration: none;
}
.card .image {
height: 100px;
padding: 2px;
overflow: hidden;
}
.card .image img {
width: 100%;
height: 100%;
object-fit: cover;
filter: grayscale(.5);
}
.card .title {
margin: 0;
padding: 10px 10px 5px 10px;
font-size: 16px;
font-weight: bold;
color: #000;
}
.card .content {
padding: 0 10px 40px 10px;
transition: color .1s linear;
}
.card .content p {
margin: 7px 0;
font-size: 14px;
opacity: .8;
}
.card .content .price {
position: absolute;
bottom: 8px;
}
.card .content .price .new-price {
font-weight: bold;
}
.card .content .price .original-price {
margin-left: 5px;
font-size: 14px;
font-style: italic;
opacity: .5;
}
/* Hover state = add box shadow, underline the title */
.card:hover {
border-color: rgba(0,0,0,.4);
box-shadow: 0 0 10px 0 rgba(0,0,0,.15);
}
.card:hover .image img,
.card:focus .image img {
filter: grayscale(0);
}
.card:hover .title {
text-decoration: underline;
}
.card a:focus {
outline: none;
}
/* Focus state = turn text blue, add large blue outline */
/* NOTE: :focus-within is not supported in IE11 or Edge as of Jan 2020. To add support, use a polyfill such as https://github.com/matteobad/focus-within-polyfill */
.card:focus-within {
border-color: hsl(204, 86%, 53%);
box-shadow: 0 0 0 2px hsl(204, 86%, 53%);
}
.card:focus-within .title,
.card:focus-within .content {
color: hsl(217, 71%, 53%);
}
.card:focus-within .title {
text-decoration: underline;
}
/** Credits at bottom */
.credits {
display: inline-block;
margin-top: 20px;
margin-left: 40px;
padding: 10px;
font-size: 14px;
color: black;
text-decoration: none;
opacity: .7;
}
.credits img {
height: 30px;
margin-left: 5px;
margin-top: -2px;
vertical-align: middle;
}
.credits:hover,
.credits:focus {
opacity: 1;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/@splidejs/splide@latest/dist/css/splide.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment