CSS basic 6 - Flexbox
Tags: css, flex, flexbox
Published: 2021-11-07 14:56:48

#Flexbox
Flexbox is a one-dimensional <strong><em>layout method for arranging items in rows or columns.</em></strong> Items flex(expand) to fill additional space or shrink to fit into smaller spaces.
For a long time, the only reliable cross-browser compatible tools available for creating CSS layouts were features like floats and positioning. These work but ain somme ways they are also limiting and frustrating. <u>Flexbox makes a lot of layout tasks much easier!</u>

To start with, we need to select which elements are to be laid out as flexible boxes. To do this, we set a special value of display on the parent element of the elements you want to affect.

```css
section {
 display: flex;
}
```
##flex-container(parent) - flex item(children)
This causes the <code>&lt;section&gt;</code> element to become a flex container and its children to become flex items.
*You can use a display value of <strong><em>inline-flex</em></strong> if you wish to lay out an element's children as flex items but have that element <u>behave like an inline element.</u>

#Flex model 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g0hazllreiqbaff1wzq9.png)
(image from mdn - https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox)


#flex-direction
- flex-direction: column;
- flex-direction: row;
- flex-direction: row-reverse;
- flex-direction: column-reverse;

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gkrltar8qmc36gju6t79.png)
This specifies which direction the <strong>main axis</strong> runs(which direction the flexbox children are laid out in).
By default this is set to row, which causes them to be laid out in a row. You can also lay out flex items in a reverse direction using the row-reverse and column-reverse values.

#justify-content
justify-content controls where the flex items sit on the main axis. The default value is flex-start which makes all the items sit at the start of the main axis.
- justify-content: flex-first;
items are packed toward start of flex-direction
- justify-content: flex-end;
items are packed toward the end of the flex direction
- justify-content: center;
items are centered along the line
- justify-content: space-between;
items are evenly distributed in the line. first item is on the start line, last item on the end line.
- justify-content: space-around;
items are evenly distributed in the line with equal space around them. *Note that <strong>visually the spaces aren't equal</strong>, since all the items have <strong>equal space on both sides.</strong> The first item will have one unit of space against the container edge, <strong><em>but two units of space between the next item</em></strong> because the next item has its own spacing that applies.
- justify-content: space-evenly;
items are distributed so that the <u>spacing between any two items(and the space to the edges) is equal</u>



```html
<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title></title>
    <style>
        body {
            font-family: sans-serif;
            box-sizing: border-box;
            font-weight: 600;
        }

        .container {
            display: flex;
            /* flex-direction: column; */
            /*
            display: inline-flex
            인라인 자신의 컨텐츠 너비만을 차지함
            */

            justify-content: flex-start;
            /* justify-content: flex-end; */
            /* justify-content: center; */
            /* justify-content: space-between; */
            /* justify-content: space-around; */
            /* justify-content: space-evenly */

            background: #f9f1f0;
            border: 2px solid black;
            width: 700px;
            height: 500px;
        }

        .box {
            background-color: pink;
            border: 2px solid black;
            width: 100px;
            height: 100px;
            margin: 10px;
            text-align: center;
            line-height: 100px;
        }


        /* vertical align  */

        .parent {
            position: relative;
            height: 400px;
            background: black;
        }

        .child {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            /* margin-top: -50px; */
            height: 100px;
            width: 50px;
            background: pink;
        }


        /* 
        horizontal align
        margin: 0 auto;
        this makes margin top, bottom 0, and auto for right, left
        */
    </style>

<body>
    <div class="container">
        <div class="box">box1</div>
        <div class="box">box2</div>
        <div class="box">box3</div>
    </div>
    <div class="parent">
        <div class="child"></div>
    </div>



</body>

</html>
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l8po6ef21adh1qdrmyl0.png)
There's cross-axis as well in flex.
The cross axis runs perpendicular to the main axis, therefore <strong><em><u>if your flex-direction(main axis) is set to row, the cross axis runs down the columns</u></em></strong> and <strong><em><u>if the flex-direction(main axis) is set to column, cross axis is row.</u></em></strong>
Find more about this [here](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox)

#align-items
align-items works based on cross-axis, it controls where the flex items sit on the cross axis. (there are spaces  between items if you use align-items: center/flex-start/flex-end)
- align-items: stretch;
- align-items: center;
- align-items: flex-start;
- align-items: flex-end;

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x3u8xl9nqi3h5yiykvcf.png)

###flex-align practice
```html
<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>flex_practice</title>
    <style>
        .container {
            width: 300px;
            height: 300px;
            background: mediumblue;
            display: flex;
            justify-content: flex-end;
            align-items: center;
        }

        .item {
            width: 80px;
            height: 80px;
            background: yellowgreen;
        }
    </style>
</head>

<body>
    <div class="container">
        <div class="item"></div>
    </div>

</body>

</html>
```

#flex-wrap
By default, flex items will all try to fit onto one line. You can change that and allow the items to wrap as needed with this property.

- flex-wrap: nowrap;
all flex items will be on one line
- flex-wrap: wrap;
flex items will wrap onto multiple lines from top to bottom (no space between columns)
- flex-wrap: wrap-reverse;
flex items will wrap onto multiple lines from bottom to top (no space between columns. it's opposite of flex: wrap;)

```html
<div class="container">
  <div class="box">box1</div>
  <div class="box">box2</div>
  <div class="box">box3</div>
  <div class="box">box4</div>
  <div class="box">box5</div>
  <div class="box">box6</div>
</div>
```
```css
.container {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  /* flex-wrap: wrap; */
  /* flex-wrap: nowrap; */
  /* flex-wrap: wrap-reverse; */
}
```


#flex-basis
It sets the initial main size of a flex item. It sets the size of the content box unless otherwise set with box-sizing.
This defines the default size of an element before the remaining space is distributed. * If the element is not a flexible item, the flex-basis property has no effect. Default value of flex-basis is auto. If set to auto, the extra space is distributed based on its flex-grow value
(it takes width and height) but if an element has flex-basis has value, width and height will be ignored.
If set to 0, the extra space around content isn’t factored in. 

#flex-grow
This defines the <u>ability for a flex item to grow if necessary.</u> It accepts a unitless value that serves as a <strong>proportion.</strong> It dictates what about of the available apce inside the flex container item should take up.
If all items have flex-grow set to 1, the remaining space in the container will be distributed <strong>equally to all children.</strong> If one of the children has a value of 2, the remaining space would take up twice as much space as the others(or it will try to, at least and negative numbers are invalid)
```css
.item {
  flex-grow: 4; /* default 0 */
}
```

#flex-shrink
This defines the ability for a flex item to shrink if necessary. Flex-shrink property sets the flex shrink factor of a flex item. If the size of all flex items is lager than the flex container, items shrink to fit according to flex-shrink.
```css
.item {
  flex-shrink: 3; /* default 1 */
}
```

#flex
Using the flex shorthand. you can use flex-grow, flex-shrink and flex-basis all at once.
```css
/* flex: flex-grow, flex-shrink, flex-basis */
flex :1; /* flex-grow:1; flex-shrink:1; flex-basis:0; */
flex :1 1 300px; /* flex-grow:1; flex-shrink:1; flex-basis:300px; */
```

#align-self
This allows the default alignment(or the one specified by align-items) to be <strong><em>overridden for individual flex items.</em></strong>(it can also overrides a grid value. In Grid, it aligns the item inside the grid area. In Flexbox, it aligns the item on the cross axis.)

- align-self: auto;
- align-self: flex-start;
- align-self: flex-end;
- align-self: center;
- align-self: baseline;
- align-self: stretch;

#order
By default, flex items are laid out in the source order. However, the order property controls the order in which they appear in the flex container.
```html
<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>flex_order</title>
    <link rel="stylesheet" href="reset.css">
    <style>
        ul {
            display: flex;
            height: 100vh;
            /* align-items: flex-end; */
        }

        li {
            width: 100px;
            height: 100px;
            background: pink;
            border: 1px solid black;
        }

        .first {
            /* the value of order property doesn't mean the location. It's more like priority.
If the value is bigger, it goes closer to the main axis and if the value is negative and smaller it goes towards the opposite side. */
            order: 2;
        }

        .second {
            /* order: 4; */
        }

        .third {
            /* order: 4; */
            order: -2;
        }

        .fourth {
            /* order: 2; */
            order: -1;
        }

        .fifth {
            order: 3;
            /* order: 1; */
            /* align-self will overriden align-items. Use if when you want to move something individually.
            */
            /* align-self: flex-start; */
        }
    </style>
</head>

<body>
    <ul>
        <li class="first">1</li>
        <li class="second">2</li>
        <li class="third">3</li>
        <li class="fourth">4</li>
        <li class="fifth">5</li>
    </ul>

</body>

</html>
```


*** Note that float, clear and vertical-align have no effect on a flex item.

* Good place to practice flex! : [Flexbox Froggy](https://flexboxfroggy.com/#ko)

* Check this [Flexbox](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) link if you'd like to read more about flexbox! It helped me to understand better!