Carousels are a useful component for displaying a series of images (or really any media). People often use carousels off the shelf, but they're quite easy to build yourself! In this post I'll go through building a Web Component for a carousel.
You can see here that as you click the next and previous buttons it scrolls through a series of images.
Building elements that don't exist
Web Components are handy tools for abstracting out common patterns in HTML. There's lots of user interface patterns that are common on the web but don't have their own elements. Instead you have to build them up yourself from other elements.
If you find yourself repeating HTML, or the complexity gets too much, it can be handy to abstract out the complexity. By creating a Web Component you can create a neat abstraction that becomes reusable and easier to understand. Plus it makes your HTML much tidier!
What does the HTML look like?
This Web Component is rather simple, it doesn't have any attributes - you just put some elements inside it.
<ben-carousel>
<img src="http://placekitten.com/360/200">
<img src="http://placekitten.com/300/200">
<img src="http://placekitten.com/420/200">
</ben-carousel>
The idea here is to stick to standard elements as much as possible and to keep it simple. The carousel is going to be in charge of displaying the content like a carousel. Then the content itself can be anything! In this case I've put in three images of cats at different sizes.
A big benefit of this approach, using Web Components, is that I can put any HTML content inside my carousel. It's just HTML! Plus I can use it in any website, no matter the library. Sticking to standards often makes things easier.
Creating the template
To begin with I wrote down the elements I'd need to create this carousel:
<template id="ben-carousel">
<button>Prev</button>
<slot></slot>
<button>Next</button>
</template>
You can see here that I've got two buttons, one for going left and one for going right. Then I've put a slot
element in, this is where the content inside will go. But this isn't quite enough for it to look like a carousel. Right now it looks like this:
So we'll need to add some styling. Once we've got it looking like a carousel we can move on to making it work like a carousel.
Here's how I styled it:
<template id="ben-carousel">
<style>
:host {
display: block;
}
#container {
display: flex;
}
#images {
display: flex;
flex-shrink: 1;
overflow: scroll;
}
</style>
<div id="container">
<button id="prev">Prev</button>
<div id="images">
<slot></slot>
</div>
<button id="next">Next</button>
</div>
</template>
First lets look at the extra elements I added. I've created a div
to wrap all of the other elements, this will be useful for layout. Then I've added another div
for the images, this will help to control how much of them is displayed.
You can also see here that I've given every element an id
. When you're working with Web Components the HTML and CSS is all scoped to within the component. So you can use id
as much as you please, it won't overlap with others on your page. This makes it much easier to write JavaScript and CSS.
Now lets look at the style here. The first part makes it so the element displays as a block
element:
:host {
display: block;
}
Next up I've styled the outer container to use display: flex
:
#container {
display: flex;
}
This makes it so that the three child elements (#prev
, #images
, and #next
) all display next to eachother horizontally. Which is key to the whole layout!
Finally we're looking at the #images
container. Here I use flex-shrink: 1
to make it so the #images
container will shrink down when the width of its parent is constrained.
#images {
flex-shrink: 1;
display: flex;
overflow: scroll;
}
I've also used display: flex
here to make the children of the #images
container (the images) all display next to eachother in a line. Finally overflow: scroll
says that the #images
container should create a scrollbar if its content has overflowed it.
The result looks like this:
That's just about everything! The only part we don't have is the buttons.
Wiring up the buttons
To wire up the buttons we'll need to write some JavaScript. First we'll set up some boilerplate for creating the carousel element:
class CarouselElement extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: 'open'});
const template = document.getElementById('carousel');
const clone = template.content.cloneNode(true);
this.shadowRoot.appendChild(clone);
}
}
customElements.define('ben-carousel', CarouselElement);
Now we want to wire up the events. Because we've already given each of our elements an id
this is rather easy. First we get each of the elements we need from the shadowRoot
:
// ... inside the constructor
const images = this.shadowRoot.getElementById('images');
const prev = this.shadowRoot.getElementById('prev');
const next = this.shadowRoot.getElementById('next');
Then we set up click handlers that scroll the images container:
// ... inside the constructor
prev.addEventListener('click', () => {
images.scrollLeft -= 100;
})
nextButton.addEventListener('click', () => {
images.scrollLeft += 100;
})
And bingo bango we've got a scrolling carousel!
Interested in Web Components?
I'm speaking about Practical Uses for Web Components at Web Directions: Code on September 17 & 24 2021. If you're interested you can use the voucher bensentme
to get 20% off!
Top comments (1)
You can rewrite:
to:
Dev.to: 5 more lessons after Web Components 101