This is the fifth project of Wes Bos'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 relevant bits for us is the transition property.
.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 slightly 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!
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