We have a flex container, each with a panel, which is a div with a background image. We set a large height to the flex container, and have the panels stretch to fill the container.
The principle behind the expanding cards is using the flex
property to control width, and applying a transition on it. The panel we click on we will add a class such that its flex value is large while its siblings' flex value is small.
container
: flex container, setting width and heightpanel
: flex item, setting flex value, background image and flex transitionactive
: when applied to a panel, it will have a large flex value, taking up more space<div class="container">
<div class="panel active">
<h3>Title 1</h3>
</div>
<div class="panel">
<h3>Title 2</h3>
</div>
<div class="panel">
<h3>Title 3</h3>
</div>
<div class="panel">
<h3>Title 4</h3>
</div>
<div class="panel">
<h3>Title 5</h3>
</div>
</div>
.panel {
background-size: cover;
background-position: center;
background-repeat: no-repeat;
flex: 1;
border-radius: 50px;
transition: flex 0.7s ease-in-out;
position: relative;
overflow: hidden;
}
.active {
flex: 20;
}
Loop through the panels, add event listener to each panel for when it's clicked, add the active class and remove the active class from any other panels that have it.
imagePanels.forEach((imagePanel, i) => {
url = `https://source.unsplash.com/random?${i}`;
imagePanel.style.backgroundImage = `url('${url}')`;
// when clicked, first remove all active classes and then add class
imagePanel.addEventListener("click", () => {
removeActiveClasses();
imagePanel.classList.add("active");
});
});
function removeActiveClasses() {
imagePanels.forEach((imagePanel) => {
imagePanel.classList.remove("active");
});
}
function createImagePanels(numImagePanels: number = 5) {
const container = document.querySelector<HTMLDivElement>(".container")!;
let url = "https://source.unsplash.com/random";
const panels: HTMLDivElement[] = [];
// create image panels
for (let i = 0; i < numImagePanels; i++) {
const imagePanel = document.createElement("div");
imagePanel.classList.add("panel");
imagePanel.style.backgroundImage = `url('${url}?${i}')`;
container.appendChild(imagePanel);
panels.push(imagePanel);
}
// add click listener: remove all active classes, then add active classes to clicked element
panels.forEach((imagePanel) => {
imagePanel.addEventListener("click", () => {
panels.forEach((imagePanel2) => {
imagePanel2.classList.remove("active");
});
imagePanel.classList.add("active");
});
});
// expand first image panel
panels[0].classList.add("active");
return document.querySelectorAll<HTMLDivElement>(".panel");
}
const imagePanels = createImagePanels();