|
| 1 | +# Exercise 5: Flex Panel Gallery |
| 2 | +Nitish Dayal, Software & Applications Developer - [Contact](http://nitishdayal.me) |
| 3 | +Last Commit Date: Dec 12, 2016 |
| 4 | + |
| 5 | +We are given a web page with five `div` HTML elements with a class `panels`, |
| 6 | + each containing three `p` HTML elements with some text. These five `div` elements |
| 7 | + are wrapped inside another `div` element with a class `panel`. Currently, these divs |
| 8 | + are stacked vertically and aren't interactive. We want to display these divs vertically |
| 9 | + and have only the middle `p` element of each `div` displayed; when a user clicks on a |
| 10 | + particular `div` element we want to expand that element and bring the two other `p` |
| 11 | + elements back into view. Update the CSS and write the JavaScript code necessary |
| 12 | + to bring this interactivity to the page. |
| 13 | + |
| 14 | +Most of this challenge focuses on working with _CSS3 flexible boxes_, or flexbox. If |
| 15 | + you're unfamiliar with flexible boxes, here's another free course provided by Wes Bos: |
| 16 | + [flexbox.io](http://flexbox.io) |
| 17 | + |
| 18 | +**SIDENOTE:** I broke up the CSS for this challenge into a separate file because that |
| 19 | + made it easier to focus on the pieces that I was working with. Organize your code |
| 20 | + however you see fit. |
| 21 | + |
| 22 | + |
| 23 | +## Guide |
| 24 | + |
| 25 | +Flex box layouts consist of a _flex container_ which contain _flex items_. |
| 26 | + We'll use the `panels` class as the _flex container_, and the `panel` class as the |
| 27 | + _flex items_. By default, _flex items_ are only as wide as they need to be in order |
| 28 | + to display their contents, but we want them to take up the entire _flex container_. |
| 29 | + Allow the _flex items_ to take up equal space and fill out the _flex container_ |
| 30 | + by allowing them to **grow**. Given that we want the content of each _flex item_ |
| 31 | + to be flexible as well, we're going to display the `panel` class as both a _flex item_ |
| 32 | + **AND** a _flex container_; this means that elements with the `panel` class will adjust |
| 33 | + themselves with respect to their _flex container_ (`div` HTML element with class `panels`), |
| 34 | + and the contents within those elements (in this case, the three `p` HTML elements) will |
| 35 | + adjust themselves with respect to their own _flex container_ (`div` HTML element with |
| 36 | + class `panels`). |
| 37 | + |
| 38 | +Horizontally and vertically center the content of the `panel` class, and modify the styling |
| 39 | + for any _children_ of the `panel` class (`.panel > *`) so that they are displayed as |
| 40 | + _flex items_ and take up 1/3 of their respective _flex container_. Create new style |
| 41 | + definitions for the first and last child elements of the `panel` class to push them |
| 42 | + off the page and to bring them back in when their parent `panel` is selected, and |
| 43 | + update the CSS for the `panel open` class so that the selected `div` will be 5x |
| 44 | + larger than the other `div` elements. ~~Holy CSS, Batman!~~ |
| 45 | + |
| 46 | +Finally, we'll write some JavaScript code to attach _event listeners_ to each `panels` |
| 47 | + element that will fire when an panel is clicked on and call their respective _event |
| 48 | + handlers_; one _event handler_ function will adjust the size of the panel, and the |
| 49 | + other will be responsible for bringing in the `p` elements that we pushed off earlier. |
| 50 | + |
| 51 | +- CSS |
| 52 | + 1. Update the styling applied to the `panels` class to display as a _flex container_: |
| 53 | + ```CSS |
| 54 | + .panels { |
| 55 | + /* ... */ |
| 56 | + display: flex; |
| 57 | + } |
| 58 | + ``` |
| 59 | + 2. Update the styling applied to each `panel` so that they equally maximize their |
| 60 | + width to fill out the _flex container_: |
| 61 | + ```CSS |
| 62 | + .panel { |
| 63 | + /* ... */ |
| 64 | + flex: 1; |
| 65 | + } |
| 66 | + ``` |
| 67 | + 3. Update the styling applied to the `panel` class so that each panel is also a _flex |
| 68 | + container_ and displays its content in _columns_: |
| 69 | + ```CSS |
| 70 | + .panel { |
| 71 | + /* ... */ |
| 72 | + display: flex; |
| 73 | + flex-direction: columns; |
| 74 | + } |
| 75 | + ``` |
| 76 | + 4. Update the styling applied to the child elements of the `panel` class so they are |
| 77 | + treated as _flex items_ and are center justified: |
| 78 | + ```CSS |
| 79 | + .panel > * { |
| 80 | + /* ... */ |
| 81 | + align-items: center; |
| 82 | + display: flex; |
| 83 | + flex: 1 0 auto; |
| 84 | + justify-content: center; |
| 85 | + } |
| 86 | + ``` |
| 87 | + 5. Create new style definitions for the _first and last child elements_ of the `panel` |
| 88 | + class so that the content is pushed off the main page until the panel is selected by the user: |
| 89 | + ```CSS |
| 90 | + .panel > *:first-child { |
| 91 | + transform: translateY(-100%); |
| 92 | + } |
| 93 | + |
| 94 | + .panel.open-active > *:first-child { |
| 95 | + transform: translateY(0); |
| 96 | + } |
| 97 | + |
| 98 | + .panel > *:last-child { |
| 99 | + transform: translateY(100%); |
| 100 | + } |
| 101 | + |
| 102 | + .panel.open-active > *:last-child { |
| 103 | + transform: translateY(0); |
| 104 | + } |
| 105 | + ``` |
| 106 | + 6. Update the styling applied to the `panel open` class so that the selected panel takes up |
| 107 | + 5x the space of the other _flex items_: |
| 108 | + ```CSS |
| 109 | + .panel.open { |
| 110 | + /* ... */ |
| 111 | + flex: 5; |
| 112 | + } |
| 113 | + ``` |
| 114 | +- JavaScript |
| 115 | + 1. Declare & define a variable as a reference to _all elements with a class `panels`_. |
| 116 | + 2. Iterate through the _HTML Node elements_ that the variable is referencing and attach |
| 117 | + an _event listener_ for the `click` event to each element, providing the name of a |
| 118 | + yet-to-be-defined function as the _event handler_. |
| 119 | + 3. Repeat step 2, this time attaching an _event listener_ for the `transitionend` event |
| 120 | + and providing a different function name for the _event handler_. |
| 121 | + 4. Define the function for Step 2 to **toggle** the class `open` on the _function context_. |
| 122 | + 5. Define the function for Step 3 to **toggle** the class `open-active` on the _function |
| 123 | + context_ **IF** the event has a property name which includes the word 'flex'. |
| 124 | + |
| 125 | +CHALLENGE 5 === DEMOLISHED |
0 commit comments