All Articles

Flex Panel Gallery with JavaScript

This is day 5 in my #javascript30 journey. This is the free course from Wes Bos that lets you brush up on your JavaScript skills via 30 projects.

Yesterday we went through an epic round of Array Cardio. You can keep track of all the projects we’re building here.

Today we’re creating an image gallery using flex panels.


As standard in this course, we start with a partially created HTML file. Currently, it looks like this:

Flex Panel Image Gallery Starting Point

The end point that we are aiming for is those image panels to be vertical and some animation in the image and text when each section is clicked.

Vertical Image Panels

We’re going to use flexbox on the panels styling and it will make them vertical. Wes has an entire (FREE) course on Flexbox if you need to brush up on it.

So to make the image panels vertical we need to:

  1. Add display: flex; to the parent style (.panels in our case)
  2. Add flex: 1; to the child style (.panel in our case).

This now has our site looking like this:

Flex Panel Image Gallery with even vertical images using flexbox

Text Display

We want the text to display horizontally centered and vertically spaced out to fill the entire height of the page. We can achieve this by nesting flex box.

First, we will need to add some more styling to .panel:

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

This will make the divs with a class of panel into a flexbox container.

Once this is done we can add styling to their children:

.panel > * {
  margin:0;
  width: 100%;
  transition:transform 0.5s;
  flex: 1 0 auto;
  display: flex;
  justify-content: center;
  align-items: center;
}

This will give us even spacing of the text just like we want:

Using nested flexbox to display the text and image divs in a spaced out fashion

Text Animation

With the even spacing of the text, we now have the final destination of the text animation. To make this animation we also need to set the default position of the text (for the start of the animation). To do this we need to move the top and bottom row of text off of the screen.

This can be done using CSS selectors and transform:

.panel > *:first-child { transform: translateY(-100%); }
.panel > *:last-child { transform: translateY(100%); }

Now we can set the styling for when the panel is active and we want to activate the transition:

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

When the panel is clicked we want the panel to increase in width & take up most of the page. Doing this is a two step process; First, we must create the styling that makes the visual changes. Second, we link the addition of this class to a mouse click.

This first step is pretty straight forward. Create a class that can be added to the panel when it is clicked:

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

The flex: 5 will mean that this panel is 5 times larger than the other panels that have a style of flex: 1.

Now we want to write some JavsScript (yay) that will activate these styles when the panel is clicked.

This script will have the following steps:

  1. Select all of the panels.
  2. Loop over each of the panels and add an event listener that is listening for a click.
  3. When a panel is clicked toggle the open class on and off.

This boils down to:

const panels = document.querySelectorAll('.panel')

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

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

Now when we click the panel we see it open and close:

Panel animations done via Javascript and css transitions

Text Animation

We want to animate the text to enter once the panel widening transition has completed.

To do this we will have to:

  1. Loop over each of the panels and add an event listener for the end of the transition.
  2. When the flex-grow transition finishes, toggle the class with the transition of the text.

This can be achieved by:

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

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

Now when we click the panel we see:

Flexbox image gallery with animation transitions


Now that everything has been done I have pushed this project live to a Firebase project. You can view it live here.

You can keep track of all the projects in this JavaScript30 challenge here.