# JavaScript-30-Day-5

![ss.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1624387959303/gfssaVcts.png)

[click for project demo](https://cenacrharsh.github.io/JS-30-DAY-5/)

So DAY-5 of [javascript30](https://javascript30.com/) 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](https://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:

```html
<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](https://www.w3schools.com/cssref/css3_pr_flex.asp), [`flex` property](https://www.w3schools.com/cssref/css3_pr_flex.asp) 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](https://www.w3schools.com/cssref/css3_pr_flex-grow.asp):

>The [`flex-grow`](https://www.w3schools.com/cssref/css3_pr_flex-grow.asp) 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:

```html
    <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`](https://www.w3schools.com/cssref/css3_pr_flex-grow.asp):

```css
    .panel-1:hover{flex-grow: 1;}
    .panel-2:hover{flex-grow: 2;}
    .panel-3:hover{flex-grow: 3;}
```

## `flex-shrink`

According to [w3School](https://www.w3schools.com/cssref/css3_pr_flex-shrink.asp):

>The [`flex-shrink`](https://www.w3schools.com/cssref/css3_pr_flex-shrink.asp) 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:

```css
    .panel-3:hover{flex-shrink: 2;}
```

## `flex-basis`

According to [w3School](https://www.w3schools.com/cssref/css3_pr_flex-basis.asp):

>The [flex-basis](https://www.w3schools.com/cssref/css3_pr_flex-basis.asp) 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:

```css
.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 another `tranlateY()` this time with a `.open-active` class which we would add to the panels when clicked using JavaScript.

```css
.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.
```javascript
const panels = document.querySelectorAll(".panel");
```

- now we use `forEach()` to add an **click** event listener to all panels
```javascript
panels.forEach((panel) => panel.addEventListener("click", toggleOpen));
```

this would add `.open()` class to panels upon getting clicked
```javascript
function toggleOpen() {
        this.classList.toggle("open");
      }
```

and this is what is in the `.open()` class. This would enlarge the  size of the panel.
```css
.panel.open {
        font-size: 40px;
        flex: 5;
      }
```

This was my first time using `classList.toggle()`.
Here is what [w3schools](https://www.w3schools.com/jsref/prop_element_classlist.asp) 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](https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle):

> The [`toggle()`](https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle) method of the [DOMTokenList](https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList) interface removes a given token from the list and returns `false`. If token doesn't exist it's added and the function returns `true`.

Here we have the function coded by Wes to show the hidden words when we click on image:

```javascript
    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 the `classList`, this class is removed from the list and returns `false`. 
- If the class `open` does not exist on the `classList`, the `open` class is added in the list and returns `true`.


- 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.
```javascript
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:
```javascript
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**

```javascript
function toggleActive(e) {
        if (e.propertyName.includes("flex")) {
          this.classList.toggle("open-active");
        }
      }
```

and with this todays project was done.

GitHub repo:
{% github cenacrharsh/JS-30-DAY-5 no-readme %}

###Blog on Day-4 of javascript30
{% link https://dev.to/cenacr007_harsh/javascript-30-day-4-13k0 %}

###Blog on Day-3 of javascript30
{% link https://dev.to/cenacr007_harsh/javascript-30-day-3-29o6 %}

###Blog on Day-2 of javascript30
{% link https://dev.to/cenacr007_harsh/javascript-30-day-2-1dmm %}

[Follow me on Twitter](https://twitter.com/cenacr007_harsh)
[Follow me on Linkedin](https://www.linkedin.com/in/kumarharsh22/)

**DEV Profile**

{% user cenacr007_harsh %}

You can also do the challenge at [javascript30](https://javascript30.com/)

Thanks [WesBos](https://github.com/wesbos) to share this with us! 😊💖

**Please comment and let me know your views**
##Thank You! 


