Flex Panel Gallery

This is the fifth project of WesBos's JS30 series. To see the whole 30 part series, click here We will be creating a panel based gallery with flexbox, CSS transitions and javascript. This is CSS heavy and the JS bits just add and removes classes from dom elements.

Here is the video :

We have the following starter code :

The HTML is straightforward -

<div class="panels">
    <div class="panel panel1">
        <p>Hey</p>
        <p>Let's</p>
        <p>Dance</p>
    </div>
    <div class="panel panel2">
        ...
    </div>
    ...
</div>

The whole page content is held in the div.panels element and each gallery item is a div.panel element. panel1 to panel5 classes just add the background. All positioning is done via Flexbox. In the CSS .panel definition, other than the basic styling, the most relavent bits for us is the transition propery.

.panel{
  transition: font-size 0.7s cubic-bezier(0.61, -0.19, 0.7, -0.11),
            flex 0.7s cubic-bezier(0.61, -0.19, 0.7, -0.11),
            background 0.2s;
}

The transition property is applied to the font-size, flex and background.

As of now the panels are horizontally aligned, we want them to be vertical. For this, make the panels element a flex container. This makes the elements align vertically.

.panels{
  display: flex;
}

Now to fix the spacing and alignment of the vertical elements -

.panel{
  flex: 1;
  justify-content: center;
  display: flex;
  flex-direction: column;
}

Here making flex: 1 ensures they spread out and take equal amount of space, making each panel itself a flex container would ensure that the text aligns in the middle.

Now for the animation. First let's move the first and last <p> of each panel above and below the screen respectively. (Note : I've done this sligthly different than Wes Bos, he made each <p> element a flex container and translated it up/down 100%, where as I've just moved them up/down 50vh without having to add any flex properties.)

panel > *:first-child { transform: translateY(-50vh); }
.panel.open-active > *:first-child { transform: translateY(0); }
.panel > *:last-child { transform: translateY(50vh); }
.panel.open-active > *:last-child { transform: translateY(0); }

When the class open-active is added to the panel, the <p>'s are moved back into view. Also the panel should get bigger when it's opened

.panel.open {
  font-size: 40px;
  flex: 5;
}

font-size increases from 2em to 40px (over 0.7s) and the width increases to 5x of what it was before!

This completes the CSS part of the animation. Try adding open and open-active classes to one of the panels below.

Now we need to do the following in javascript!

  1. Listen for 'click' event on a panel, add the 'open' class
  2. Listen for 'transitionend' and add the 'open-active' class

first part -

function toggleOpen(){
 this.classList.toggle('open')
}

document.querySelectorAll('.panel')
        .forEach(panel => panel.addEventListener('click'), toggleOpen)

second part -

function toggleActive(e){
  if(e.propertyName.includes('flex')){
    this.classList.toggle('open-active')
  }
}

document.querySelectorAll('.panel')
        .forEach(panel => panel.addEventListener('transitionend'), toggleActive)

That completes our web page! The final code