<div class="carousel">
<button class="tile">
<div class="sr-only">tile 1 of 5,</div>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/3609497/galina-n-300x300.jpg" class="product-image" alt="Succulent in planter">
<div class="overlay">
<div class="quick-view-button">Quick view</div>
</div>
</button>
<button class="tile">
<div class="sr-only">tile 2 of 5,</div>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/3609497/curology-300x300.jpg" class="product-image" alt="Lotion bottle with text Curology on it">
<div class="overlay">
<div class="quick-view-button">Quick view</div>
</div>
</button>
<button class="tile">
<div class="sr-only">tile 3 of 5,</div>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/3609497/imani-clovis-300x300.jpg" class="product-image" alt="Black running shoe falling downward">
<div class="overlay">
<div class="quick-view-button">Quick view</div>
</div>
</button>
<button class="tile">
<div class="sr-only">tile 4 of 5,</div>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/3609497/rachit-tank-300x300.jpg" class="product-image" alt="Wristwatch laid on table">
<div class="overlay">
<div class="quick-view-button">Quick view</div>
</div>
</button>
<button class="tile">
<div class="sr-only">tile 5 of 5,</div>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/3609497/deanna-alys-300x300.jpg" class="product-image" alt="Lotion bottle with succulent and water bottle in background">
<div class="overlay">
<div class="quick-view-button">Quick view</div>
</div>
</button>
</div>
<a href="https://allyant.com" class="credits" target="_blank">
Built by<img src="https://assets.codepen.io/3609497/allyant-logo.svg" alt="Allyant">
</a>
<div class="dialog is-hidden" role="dialog" aria-modal="true">
<div class="overlay">
<button class="close-button first-focusable-element">
<span class="fa fa-times" aria-hidden="true"></span>
<span class="sr-only">Close</span>
</button>
<h2 class="title">Quick view</h2>
<p>This is a fake modal. Press Escape to close, or activate any of the buttons.</p>
<button class="ok-button last-focusable-element">OK</button>
</div>
</div>
:root {
--tile-width: 200px;
--tile-margin: 10px;
--carousel-height: 175px;
}
body {
margin: 10px;
}
.carousel {
position: relative;
width: calc(100% - 100px);
max-width: 700px;
margin-left: 50px;
}
.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;
}
.previous-button {
position: absolute;
left: -50px;
top: 60px;
}
.next-button {
position: absolute;
right: -50px;
top: 60px;
}
.tile {
height: var(--carousel-height);
position: relative;
padding: 0;
border: 0;
background: none;
cursor: pointer;
}
.tile:focus {
outline: 0;
}
.slick-slide:not(:last-of-type) {
margin-right: var(--tile-margin);
}
.tile .product-image {
width: 100%;
height: 100%;
object-fit: cover;
}
.tile .overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0,0,0,.6);
transition: opacity .1s linear;
opacity: 0;
}
.tile:focus .overlay,
.tile:hover .overlay {
opacity: 1;
}
.tile .overlay .quick-view-button {
padding: 10px 15px;
background: rgba(0,0,0,.7);
border: 3px solid white;
box-shadow: 0 0 15px 0 rgba(0,0,0,.6);
color: white;
font-size: 14px;
text-transform: uppercase;
font-weight: bold;
}
.dialog {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,.6);
z-index: 100;
display: flex;
justify-content: center;
align-items: center;
}
.dialog.is-hidden {
display: none;
}
.dialog .overlay {
background-color: white;
border-radius: 10px;
position: relative;
width: 80%;
max-width: 400px;
padding: 20px;
}
.dialog .overlay .close-button {
position: absolute;
top: 15px;
right: 10px;
background: none;
border: 0;
font-size: 18px;
cursor: pointer;
}
.dialog .overlay .title {
margin: 0;
}
.dialog .overlay .ok-button {
padding: 10px 15px;
background: royalblue;
border: 0;
border-radius: 5px;
color: white;
cursor: pointer;
}
.dialog .overlay .ok-button:focus {
outline-offset: 5px;
}
.credits {
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;
}
var tiles = [];
var dialog, dialogOverlay, dialogCloseButton, dialogOkButton;
var triggeringElement;
window.addEventListener('DOMContentLoaded', function(e) {
dialog = document.querySelector('.dialog');
dialogOverlay = dialog.querySelector('.overlay');
dialogCloseButton = dialogOverlay.querySelector('.close-button');
dialogOkButton = dialogOverlay.querySelector('.ok-button');
$('.carousel').on('init', function(e, slick) {
tiles = document.querySelectorAll('.carousel .tile');
tiles.forEach(function(tile) {
tile.addEventListener('click', openDialog);
});
});
$('.carousel').slick({
slidesToShow: 3,
prevArrow: '<button class="previous-button is-control">' +
' <span class="fas fa-angle-left" aria-hidden="true"></span>' +
' <span class="sr-only">Previous slide</span>' +
'</button>',
nextArrow: '<button class="next-button is-control">' +
' <span class="fas fa-angle-right" aria-hidden="true"></span>' +
' <span class="sr-only">Next slide</span>' +
'</button>',
responsive: [
{
breakpoint: 575,
settings: {
slidesToShow: 2
}
},
{
breakpoint: 375,
settings: {
slidesToShow: 1
}
}
]
});
dialogCloseButton.addEventListener('click', closeDialog);
dialogOkButton.addEventListener('click', closeDialog);
dialog.addEventListener('click', handleDialogClicks);
dialog.addEventListener('keydown', handleDialogKeypresses);
});
function openDialog(e) {
e.preventDefault();
triggeringElement = e.target;
dialog.classList.remove('is-hidden');
dialogCloseButton.focus();
}
function closeDialog() {
triggeringElement.focus();
dialog.classList.add('is-hidden');
}
function handleDialogClicks(e) {
if(!dialogOverlay.contains(e.target)) {
closeDialog();
}
}
function handleDialogKeypresses(e) {
switch(e.key) {
case 'Escape':
closeDialog();
break;
case 'Tab':
if(e.shiftKey && document.activeElement === dialogCloseButton) {
e.preventDefault();
dialogOkButton.focus();
} else if(!e.shiftKey && document.activeElement === dialogOkButton) {
e.preventDefault();
dialogCloseButton.focus();
}
break;
}
}