Learning to build a better slider part three
Didn’t get much further today after noticing that I goofed up on my JavaScript from yesterday. I think the lazy loading works properly now, but I’m still trying to troubleshoot an issue with the SVG within the img’s src. Gotta try again tomorrow.
scroll or use your arrow keys to see more kittens
scroll for more cute kittens
use your left and right arrow keys to see more kittens
swipe to see more kittens
View the code:
HTML and JS
<div class="code-block">
<div class="gallery">
<div role="region" aria-label="gallery" tabindex="0" aria-describedby="instructions">
<ul>
<li>
<figure>
<img class="dots" src='data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 6 2" stroke="currentColor" stroke-dasharray="1,0.5"><path d="M1,1 5,1" /></svg>' data-src="http://placekitten.com/200/304" alt="placeholder image of a cute kitteh">
<noscript>
<img src="http://placekitten.com/230/304" alt="placeholder image of a cute kitteh">
</noscript>
<figcaption>Gene Hackman</figcaption>
</figure>
</li>
<li>
<figure>
<img class="dots" src='data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 6 2" stroke="currentColor" stroke-dasharray="1,0.5"><path d="M1,1 5,1" /></svg>' data-src="http://placekitten.com/220/304" alt="placeholder image of a cute kitteh">
<noscript>
<img src="http://placekitten.com/230/304" alt="placeholder image of a cute kitteh">
</noscript>
<figcaption>Frederick Von Lickshimself</figcaption>
</figure>
</li>
<li>
<figure>
<img class="dots" src='data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 6 2" stroke="currentColor" stroke-dasharray="1,0.5"><path d="M1,1 5,1" /></svg>' data-src="http://placekitten.com/230/304" alt="placeholder image of a cute kitteh">
<noscript>
<img src="http://placekitten.com/230/304" alt="placeholder image of a cute kitteh">
</noscript>
<figcaption>Purrecious</figcaption>
</figure>
</li>
<li>
<figure>
<img class="dots" src='data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 6 2" stroke="currentColor" stroke-dasharray="1,0.5"><path d="M1,1 5,1" /></svg>' data-src="http://placekitten.com/200/310" alt="placeholder image of a cute kitteh">
<noscript>
<img src="http://placekitten.com/200/310" alt="placeholder image of a cute kitteh">
</noscript>
<figcaption>Fuzzball</figcaption>
</figure>
</li>
</ul>
<!-- list of gallery pictures -->
</div>
<div id="instructions" class="instructions">
<p id="hover-and-focus">scroll or use your arrow keys to see more kittens</p>
<p id="hover">scroll for more cute kittens</p>
<p id="focus">use your left and right arrow keys to see more kittens</p>
<p id="touch">swipe to see more kittens</p>
</div>
<ul aria-label="gallery controls">
<li>
<button id="previous" aria-label="previous"><</button>
</li>
<li>
<button id="next" aria-label="next">></button>
</li>
</ul>
</div>
</div>
<script>
// ---------
// Variables
// ---------
/* Variables for lazy loading of images - Another helpful bit of JS from Heydon Pickering's book, Inclusive Components - https://inclusive-components.design/a-content-slider/ */
const gallery = document.querySelector('[aria-label="gallery"]')
const slides = gallery.querySelectorAll('li')
const instructions = document.getElementById('instructions')
const observerSettings = {
root: gallery,
rootMargin: '-10px'
}
/* end of variables for lazy loading of images in slider */
// ---------
// Functions
// ---------
// ---------
// Events
// ---------
// Listen for a touch and add a touch class to the body element. Script and overall concepts by Heydon Pickering, https://inclusive-components.design/a-content-slider/. Gosh he's good at this stuff.
window.addEventListener('touchstart', function
touched() {
document.body.classList.add('touch');
window.removeEventListener('touchstart', touched, false)
}, false)
// IntersectionObserver script to help with lazy loading of slider images
if ('IntersectionObserver' in window) {
Array.prototype.forEach.call(slides, function(slide) {
let img = slide.querySelector('figure > img');
});
const callback = (slides, observer) => {
Array.prototype.forEach.call(slides, function (entry) {
if (!entry.isIntersecting) {
return;
}
let img = entry.target.querySelector('img');
img.onload = () =>
img.classList.remove('dots');
img.setAttribute('src', img.dataset.src);
observer.unobserve(entry.target);
})
}
const observer = new IntersectionObserver(callback, observerSettings);
Array.prototype.forEach.call(slides, t => observer.observe(t));
} else {
Array.prototype.forEach.call(slides, function (s) {
let img = s.querySelector('img');
img.setAttribute('src', img.getAttribute('data-src'));
img.classList.remove('dots');
})
}
</script>
CSS
.code-block {
max-width: 60em;
margin: 1rem auto;
}
[aria-label="gallery"] {
border: 2px solid;
padding: 1rem;
overflow-x: scroll;
-webkit-overflow-scrolling: touch;
-webkit-scroll-snap-type: mandatory;
-ms-scroll-snap-type: mandatory;
scroll-snap-type: mandatory;
-webkit-scroll-snap-points-x: repeat(100%);
-ms-scroll-snap-points-x: repeat(100%);
scroll-snap-points-x: repeat(100%);
}
[aria-label="gallery"]:focus, [aria-label="galler controls"]:focus {
outline: 4px solid dodgerblue;
outline-offset: -6px;
}
[aria-label="gallery controls"] button:focus {
outline-offset: -4px;
}
[aria-label="gallery"] ul {
display: flex;
padding-left: 0;
margin: 0;
}
[aria-label="gallery"] li {
list-style-type: none;
flex: 0 0 100%;
padding: 2rem;
text-align: center;
}
[aria-label="gallery"] figure {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 50vh;
}
[aria-label="gallery"] figcaption {
padding: 0.5rem;
font-style: italic;
text-align: center;
}
[aria-label="gallery"] img {
max-width: 100%;
max-height: calc(100%-2rem);
margin-top: 2rem;
}
.instructions p {
background-color: #030303;
color: #fff;
text-align: center;
padding: 1rem;
margin-top: 0;
}
#focus, #hover, #hover-and-focus, #touch {
display: none;
}
[aria-label="gallery"]:focus + .instructions #focus,
[aria-label="gallery"]:hover + .instructions #hover {
display: block;
}
[aria-label="gallery"]:hover + .instructions #hover + #focus {
display: none;
}
[aria-label="gallery"]:hover:focus + .instructions #hover-and-focus {
display: block;
}
[aria-label="gallery"]:hover:focus + .instructions #hover-and-focus ~ * {
display: none;
}
.touch .instructions p {
display: none !important;
}
.touch .instructions #touch {
display: block !important;
}
.gallery {
position: relative;
}
[aria-label="gallery controls"] li {
list-style: none;
}
[aria-label="gallery controls"] button {
position: absolute;
top: 0;
background: #010101;
color: #fff;
border: 2px solid #010101;
border-radius: 0;
width: 3rem;
height: calc(60vh + 4px);
letter-spacing: 1px;
font-weight: bold;
cursor: pointer;
}
#previous {
left: 0;
}
#next {
right: 0;
}
@keyframes flash {
to {
opacity: 0;
}
}
img.dots {
max-width: 5rem;
max-height: 5rem;
padding: 0;
animation: flash 0.5s linear infinite;
}