Day 1 - Expanding Cards

example:

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.

HTML structure

<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>

Css

.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;
}

JavaScript

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");
  });
}

Complete

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();