A responsive product card carousel built with Splide, using accessibility improvements crafted by expert accessibility specialists at Accessible360.
Created
November 5, 2021 15:19
-
-
Save olh/18497838738c8cdb6c8b60c17bce1a95 to your computer and use it in GitHub Desktop.
Splide - linked product cards
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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('>'); | |
| }); | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <script src="https://cdn.jsdelivr.net/npm/@splidejs/splide@latest/dist/js/splide.min.js"></script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| 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; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <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