Flexbox Basics for Noobs
Published: 2021-01-17 18:04:58



## Flexbox
Flexbox(flexible box) is **one-dimensional** layout module that allows you to build layouts, align and distribute space among flex items inside flex container, regardless of their sizes. And Flexbox is meant to be used to build small-scale layouts and used to distribute space among components, and for large-scale-layouts Grid should be used. And the combination of Grid and Flexbox has become very powerful as with Grid you can build any complex layout while with Flexbox you can create simple layouts and use for to aligning items inside components.
And Flexbox solves the problem of building layouts with ease where before Flexbox came to the game, we have to build layouts with tables, floats, positioning all of which was not intended to build layouts and were quite painful to build layouts as we had to do hacks like clear fix and so on.
Flexbox can be used for
* Creating menus, navbars
* Equal columns
* Aligning input and button in the same row 
* And more


## Flexbox Core
So before learning about all the properties that are on flexbox, we should learn the core functionality of how flexbox works so that all flexbox properties that we use make sense and we can make better decisions when using flexbox. So have a look at the image below and I'm explaining each one of them in detail after that.
![alt text](https://api.ed.team/public-files/bloginlineimg/dc3109db-181d-4c21-b816-b6ff1ebec061.png)


 
  

 

**main-axis** is like arrow and arrow by default points to right but we can change the direction of the arrow to left, bottom, top with **flex-direction** values

**main-start** & **main-end** -  is where flex items are placed from **main-start** to **main-end**     and direction of how flex items are placed changes based on **flex-direction** value. By default flex items are placed from left to right horizontally when **flex-direction: row;** in that case main-axis arrow points to the right. And flex items are placed from right to left horizontally when **flex-direction: row-reverse;** and main-axis arrow points to left in that case. And flex items are placed from top to bottom vertically when **flex-direction: column;** in that case main-axis arrow points to the bottom. And flex items are placed from bottom to top vertically when **flex-direction: column-reverse;** and in that case main-axis arrow points to top

**main-size** - is width/height of flex items based on the direction of main-axis 

**cross-axis** can also consider as an arrow and by default, it points to the bottom but it changes to point to the right when **flex-direction: column or column-reverse**

**cross-start** & **cross-end** is how flex items are placed inside container. By default cross-axis arrow points to the bottom and in that mode, flex items are positioned from **cross-start** to **cross-end** vertically which is top to bottom but the direction of the cross-axis changes when **flex-direction: column**. And in that case flex items are placed horizontally from left to right  

**cross-size** - is width/height of flex items   based on the direction of cross-axis

**flex-container** is when the HTML element whose display property is set to flex thus become the container for flex items. *NOTE*: flex items can also be a flex container

**flex-item** is a flexible item when its direct parent's display property is set to flex


## Flex Container Properties
There are types of properties that are available only on flex container ones that can be applied only on flex item itself. In this section, we are learning all major flex container properties. 


### Justify Content
So **justify-content**  moves all flex items in the main-axis and the picture below you can how **justify-content** moves flex items on the main axis. And it has the following values 

![alt text](https://coursesweb.net/addons/css/flexbox-justify-content.png)

* **flex-start** - moves all flex items to the **main-start** of the flex container, and regardless of which side the main-axis arrow points to, flex items are always placed at the **main-start** of the container before other values in **justify-content** is used
* **flex-end** - moves all flex items to the **main-end** of flex container. And based on where the main-axis arrow points to, flex items could be placed on the right side, left side, topside, and bottom side of the flex container
* **center** - moves all flex items to the center of the main-axis
* **space-between** - creates equal space in between flex items but not any space in **main-start** and **main-end** of flex items
* **space-around** - creates equal space between flexbox items and half of that space in **main-start** and **main-end** of flex items
* **space-evenly** - creates equal space both in between flex items and in **main-start** and **main-end** of flex items



### Align Items
So **align-items** moves flex items in cross-axis. As I've told you if **flex-direction: row or row-reverse** flex items are placed vertically top to bottom in the container but if **flex-direction: column or column-reverse** then flex items are positioned horizontally from left to right. And it few values that by using them we can align flex items in cross-axis. Please look at the picture below to have the visual mental image of how **align-items** work.

![alt text](https://www.webcreatorbox.com/wp-content/uploads/2017/03/align-items-1.png)

* **stretch** -  is the default value in which flex items  occupy available space in the cross axis
* **flex-start** -  moves all flex items to **cross-start** of cross axis
* **flex-end** -  moves all flex items to **cross-end** of  cross axis
* **center** - moves flex items to the center of the cross axis
* **baseline** - moves the bottom of all flex items' content into the same line. This is especially useful when one of the flex items is larger than other flex items. So to put them in the same line we use this value.


### Centering with Justify Content and Align Content
So instead of using all other hacks like transforming elements, positioning elements to center it inside the container. we can just use a combination of few flexbox declarations to center the element. It's that easy, look at the example below
```CSS
    .container {
        display: flex;
        justify-content: center;
        align-items: center;
    }

```

### Flex Wrap
So basically setting **flex-wrap**  other than no-wrap in flex container makes each flex item move to the next line as soon as its set width gets smaller. So have look at the picture below to make sense of it. And there are few values that I'm explaining in detail below

![alt-text](https://codropspz-tympanus.netdna-ssl.com/codrops/wp-content/uploads/2014/10/flex-wrap-illustration.jpg)

* **no-wrap** - is the default value and in that mode, even if flex items shrink they do not move to the new line.
* **wrap** - makes flex items starting from last to the first move to a new line as soon as their width starts to get smaller than the specified width. In **wrap** flex items that move to a new line earlier will be on the bottom of the flex items which move to a new line later
* **wrap-reverse** - makes flex items starting from last to the first move to the top of them when their width gets smaller. In **wrap-reverse** flex items that move to a new line earlier will be on the top of the flex items which move later to the new line


### Flex Direction
So **flex-direction**  changes the direction of the main axis (default one main-axis arrow points to the right). See the picture below to form a mental image of how this property works. 

![alt text](https://th.bing.com/th/id/OIP.yH_AxlvjD4FCJ23J0mm3dQHaGB?pid=Api&rs=1)

* **row** - is default and in that mode main-axis arrow points to right
* **row-reverse** - changes direction of main-axis to make it points to left
* **column** - makes main-axis arrow points to bottom
* **column-reverse** - sets main-axis arrow points to top

**NOTE**: So setting **flex-direction: column or column-reverse** when flex item's width is set width flex-basis, result in value declared in flex-basis applying to the height of the flex item when above-mentioned values applied to flex-direction. **NOTE**: this only applies for flex-basis not for other measurement units.


### Flex Flow
So **flex-flow** is the way to define **flex-direction** and **flex-wrap** in a single declaration which is a cool way in my opinion. And they are defined like this.  
```CSS
    .container {
        display: flex;
        flex-flow: row wrap;
    }
```


### Align Content
**align-content**  has the same values as justify-content. But it only works when "flex-wrap wrap or wrap-reverse" is applied to the flex container and also when there is more than one line of flex items and is used to move flex items in the cross axis. Have a look at the picture below to get an idea of how it works. I'

![alt text](https://www.webcreatorbox.com/wp-content/uploads/2017/03/align-content.png)

* **stretch** - is the default value in which all flex items occupy available space in cross-axis
* **flex-start** - moves bunch of flex items to the **cross-start** of flex container
* **flex-end** - moves all flex items to the **cross-end** of flex container
* **center** - moves all flex items to the center of cross-axis
* **space-between** - creates equal space in between flex items but not any space in **cross-start** and **cross-end** of flex items
* **space-around** - creates equal space between flexbox items and half of that space in **cross-start** and **cross-end** of flex items
* **space-evenly** - creates equal space both in between flex items and in **cross-start** and **cross-end** of flex items

**NOTE**: ::fistline and ::firstletter don't work on flex containers


## Flex Item Properties


### Align Self
**align-self** overrides the declared value of **align-items** if it's set on the parent element or even if it's not applied, it moves individual flex item it's used on in cross-axis of the container. And all those values on **align-items** also apply the same to **align-self**. And have a look at the image below to have a visual mental image for this property

![alt text](https://codropspz-tympanus.netdna-ssl.com/codrops/wp-content/uploads/2015/02/align-self-illustration.png)
 

### Flex Grow
**flex-grow** only accepts positive integers and it tells the available portion of container space(width)  is distributed among sibling flex items.   The higher the flex-grow value on a flex item, the more available space it occupies and the faster it'll grow relative to its sibling flex items. And for example, if one flex item has a flex-grow of 2 and other items have flex-grow 1, then it'll grow twice more than its sibling flex items.


### Flex Shrink
**flex-shrink** also only accepts positive integers and works like **flex-grow** but instead of growing, it'll make flex item shrink. The higher value in flex-shrink has in flex item, the faster it'll shrink(gets smaller) relative to its sibling flex items.


### Flex Basis
**flex-basis**  defines starting width of flex items. This means is that before the viewport gets smaller,  the width of the flex item will be what is defined in **flex-basis** but shrinks when the viewport gets smaller.

### Flex
**flex** is cool property that is shorthand for defining **flex-grow** | **flex-shrink**  | **flex-base** in single declaration. And by default values in **flex** is set to **flex: 1 0 auto**. Using **flex-shrink**  | **flex-base** is an optional but you have to have **flex-grow** in it.  
It's suggested to use this shorthand property instead of setting those 3 properties individually. As **flex** can intelligently set other properties.


### Order
**order** accepts only integers and it changes the order of flex items in which flex items that have smaller value on their order property will be before all other flex items that have bigger value on their order property and flex items with the biggest value on order property that is used on them will be after all flex item that has smaller value for order property on them. And default order value in all flex items are 0 in which are placed in the source order in the container

**NOTE**: float, clear and vertical-align don't work on flex items.
  


## Browser Support
You can check browser support for flexbox and its properties on this [website](https://caniuse.com/). And If certain browsers don't support certain flexbox properties then include vendor prefixes of those browsers. Below a few of the major browser vendor prefixes.
* iOS: -webkit-
* Safari: -webkit-
* Firefox: -moz-
* Chrome: -webkit-
* Opera: -o-
* Internet Explorer & Microsoft Edge: -ms-

```CSS
    .container {
        -webkit-display: flex;
        -moz-display: flex;
        -ms-display: flex;
        -o-display: flex;
        display: flex;
    }
```




## Projects to Built
So You've learned a lot about the core of the Flexbox and now it's time to practice what you've learned to cement it in your brain. So I recommend building a few projects below. I recommend you to do push yourself to do those projects on your own without looking at their source code
* Built Youtube navbar
* Built projects in [link](https://webdesign.tutsplus.com/tutorials/exercises-in-flexbox-simple-web-components--cms-28049)
* Built one or two projects in [here](https://bashooka.com/coding/20-examples-of-ui-components-built-using-css-flexbox/) or more if you want to 


## Websites For Exercising
* Flexbox [froggy](http://flexboxfroggy.com/)
* Freecodecamp [flexbox section](https://www.freecodecamp.org/learn/responsive-web-design/css-flexbox/use-display-flex-to-position-two-boxes)


## Resources to dive deeper
*  Flexbox on [mdn](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox)
*  A Complete Guide to [flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/)
*  Flexbox by Net [Ninja](https://www.youtube.com/results?search_query=flexbox+net+ninja) my favourite one


## Summary
 * So you've learned the fundamentals of Flexbox
 * You can now implement Flexbox on your projects to build flexible layouts
 * PRACTISE PRACTISE PRACTISE to internalize what you've learned
 * Next article is going to be about Grid