So DAY-5 of javascript30 heavily focused on the CSS flex
property.
Before starting I would like to mention Wes has another one of these tutorials like javascript30 for flex
called flexbox.io. I think I might try it out after I am done with javascript30.
In this lesson, you make a photo gallery page where each image is shown and clicking on an image will expand it to take up more space to get a better look. With the expanding image, some text also animates in from the top and bottom giving a nice, smooth feel to the whole thing.
This is initial html setup that was given:
<div class="panels">
<div class="panel panel1">
<p>Hey</p>
<p>Let's</p>
<p>Dance</p>
</div>
<div class="panel panel2">
<p>Give</p>
<p>Take</p>
<p>Receive</p>
</div>
<div class="panel panel3">
<p>Experience</p>
<p>It</p>
<p>Today</p>
</div>
<div class="panel panel4">
<p>Give</p>
<p>All</p>
<p>You can</p>
</div>
<div class="panel panel5">
<p>Life</p>
<p>In</p>
<p>Motion</p>
</div>
</div>
CSS
We started off by adding a display:flex
on the .panels
class so that all 5 panels are displayed side by side.
But this left a lot of empty space on the page so to make the panels cover the full page equally we go to each individual panel and tell them we've got all this extra space here so split it amongst yourselves and we do so by adding a flex:1
to the .panel
class.
flex:1
means each of the panels is going to evenly distribute the extra space among each other.
I did more research about flex
and this is what is learned:
flex
property
According to w3School, flex
property is a shorthand version of another 3 properties:
The flex property is a shorthand property for:
- flex-grow
- flex-shrink
- flex-basis
The flex property sets the flexible length on flexible items.
Note: If the element is not a flexible item, the flex property has no effect.
Let's see these properties closer:
flex-grow
According to w3School:
The
flex-grow
property specifies how much the item will grow relative to the rest of the flexible items inside the same container.
What does it mean?
If I have three panels:
<div class="panel-1"></div>
<div class="panel-2"></div>
<div class="panel-3"></div>
We can set what of them is greater than other relatiely with each other, using flex-grow
:
.panel-1:hover{flex-grow: 1;}
.panel-2:hover{flex-grow: 2;}
.panel-3:hover{flex-grow: 3;}
flex-shrink
According to w3School:
The
flex-shrink
property specifies how the item will shrink relative to the rest of the flexible items inside the same container.
What does it mean?
Using the same last HTML panel example, we can set how and what of these panels is shrunk. Here I chose the middle panel:
.panel-3:hover{flex-shrink: 2;}
flex-basis
According to w3School:
The flex-basis property specifies the initial length of a flexible item.
What does it mean?
Using the same last HTML panel example, we can set the length of a flex item. Here I chose the middle panel to be initially bigger than others:
.panel-1:hover{flex-basis: 15%;}
.panel-2:hover{flex-basis: 70%;}
.panel-3:hover{flex-basis: 15%;}
Next thing I learned was when we tried to center align the text where I came to know that an element in CSS can both be a flex-item and flex-container that is we can nest multiple flex together.
Now we'll take the upper text all the way up and lower text all the way down and for that we used
translateY()
but we want the words to comeback when clicked and expanded so we add anothertranlateY()
this time with a.open-active
class which we would add to the panels when clicked using JavaScript.
.panel > *:first-child {
transform: translateY(-100%);
}
.panel.open-active > *:first-child {
transform: translateY(0);
}
.panel > *:last-child {
transform: translateY(100%);
}
.panel.open-active > *:last-child {
transform: translateY(0);
}
JavaScript
- first we use
querySelectorAll()
to get a NodeList of all the panels.
const panels = document.querySelectorAll(".panel");
- now we use
forEach()
to add an click event listener to all panels
panels.forEach((panel) => panel.addEventListener("click", toggleOpen));
this would add .open()
class to panels upon getting clicked
function toggleOpen() {
this.classList.toggle("open");
}
and this is what is in the .open()
class. This would enlarge the size of the panel.
.panel.open {
font-size: 40px;
flex: 5;
}
This was my first time using classList.toggle()
.
Here is what w3schools says:
toggle(class, true|false) Toggles between a class name for an element.
The first parameter removes the specified class from an element, and returns false.
If the class does not exist, it is added to the element, and the return value is true.The optional second parameter is a Boolean value that forces the class to be added or removed, regardless of whether or not it already existed. For example:
Remove a class: element.classList.toggle("classToRemove", false);
Add a class: element.classList.toggle("classToAdd", true);
Accordding to MDN:
The
toggle()
method of the DOMTokenList interface removes a given token from the list and returnsfalse
. If token doesn't exist it's added and the function returnstrue
.
Here we have the function coded by Wes to show the hidden words when we click on image:
function toggleOpen() {
this.classList.toggle('open');
}
According with what we read before about toggle()
method, this function verifies if the class open
exists or not in the classList
of that element, which is being verified:
- If the class
open
exists on theclassList
, this class is removed from the list and returnsfalse
. If the class
open
does not exist on theclassList
, theopen
class is added in the list and returnstrue
.next event listener we are going to add is
transitionend
which would cause the text to appear by adding the.open-active
class as soon as the panel finishes expanding transition.
panels.forEach((panel) =>
panel.addEventListener("transitionend", toggleActive)
);
but now instead of simply adding .open-active
class we have to check first because more than one transition is ending here.
We can check that out by using:
function toggleActive(e) {
console.log(e.propertyName);
}
in our case flex-grow
and font-size
events are ending. But we need to concern ourselves with only flex-grow.
Now Wes mentioned one important thing here:
Safari transitionend event.propertyName === flex
Chrome + FF transitionend event.propertyName === flex-grow
So to cover our bases we'll check if the transition includes the word flex instead of explicitly checking for flex-grow
function toggleActive(e) {
if (e.propertyName.includes("flex")) {
this.classList.toggle("open-active");
}
}
and with this todays project was done.
GitHub repo:
Blog on Day-4 of javascript30
Blog on Day-3 of javascript30
Blog on Day-2 of javascript30
Follow me on Twitter
Follow me on Linkedin
DEV Profile
You can also do the challenge at javascript30
Thanks WesBos to share this with us! 😊💖
Please comment and let me know your views
Top comments (6)
EPIC
thanks a lot.
GREAT
thanks
Good job bud 👍🏽
thanks