# Flexbox

  • As we saw earlier in this course, display: flex (a.k.a. flexbox) is one of the possible display types
  • The idea behind the CSS Flexible Box Layout Module is that you should be able to spread all parts of a web page horizontally and vertically with a "flexible flow"
  • Almost all modern CSS frameworks like Bootstrap and Materialize use flexbox to position elements on a page (e.g. grid, cards, navigation bars, ...)
  • When you set an element to display:flex only the element itself (the flex container) and its DIRECT children (flex items) are affected!

Flex container and child

  • Before we discuss the different properties of the flex container and the flex items, let's look what happens when you add display: flex to the .parent class

display:flex

REMARKS

  • It doesn't matter if the flex item is a block element (div, hx, p, ...) or an inline element (span, img, ...). When you set display: flex, all flex items behave exactly the same!
    • Because all flex items behave the same, we will discuss the different properties of flexbox using div tags
  • If the flex item elements have no width/height, they collapse to their actual content

# Flex container (parent)

# flex-wrap

  • The flex-wrap property determines how the flex items behave if they don't fit inside the flex container
EMMET instruction result description
fxw:n + TAB flex-wrap: nowrap; (default) all flex items overflow the flex container
fxw:w + TAB flex-wrap: wrap; all flex items wrap into the flex container
fxw:wr + TAB flex-wrap: wrap-reverse; all flex items wrap into the flex container, but in reverse order

# flex-direction

  • The flex-direction property determines how the flex items are placed inside the flex container
EMMET instruction result description
fxd:r + TAB flex-direction: row; (default) all flex items are placed in a row from left to right
fxd:rr + TAB flex-direction: row-reverse; all flex items are placed in a row from right to left
fxd:c + TAB flex-direction: column; all flex items are placed in a column from top to bottom
fxd:cr + TAB flex-direction: column-reverse; all flex items are placed in a column from bottom to top

REMARKS

  • When you set the flex-direction to column or column-reverse, all flex items span the total width of the flex container
  • When dealing with flexboxes, we are not speaking of a horizontal/vertical direction, but of a main axis/cross axis

Main vs cross axis

  • The other flex properties (flex-wrap, justify-content, align-items, align-content) basically behave the same for the flex-direction settings row or column, but the lay-out may look very different

# flex-flow (shorthand)

  • flex-flow is just a shorthand for flex-direction and flex-wrap. The order of the values does not matter. For example:
    • flex-flow: row wrap;
    • flex-flow: column-reverse wrap-reverse;

# justify-content (main axis)

  • The justify-content property determines how the flex items are distributed along the main axis of the flex container
  • The table below contains the most used (not all) values for this property
EMMET instruction result description
jc:fs + TAB justify-content: flex-start; (default) all flex items are placed towards the start of the main axis
jc:fe + TAB justify-content: flex-end; all flex items are placed towards the end of the main axis
jc:c + TAB justify-content: center; all flex items are placed around the center of the main axis
jc:sb + TAB justify-content: space-between; distribute all flex items evenly on the main axis
(the first flex item is placed at the start of the main axis,
the last flex item is placed at the end of the main axis)
jc:sa + TAB justify-content: space-around; distribute all flex items evenly on the main axis
(flex items have a half-size space on either end)
justify-content: space-evenly; distribute all flex items evenly on the main axis
(flex items have an equal space between them)

REMARK 1

  • By adding some extra content to one of the flex items, all flex items are stretched along the cross axis
    • This (default) behavior will be discussed in more detail in the next part on the align-items property

REMARK 2

  • When setting the flex-direction to column, it seems that justify-content behaves very differently
    • This can be confusing at first sight, but this behavior is very normal at this point (as the flex items are stretched along the cross-axis by default)
  • The flex CONTAINER has no width or height explicitly set, so it uses the default values of the div tag
    • The default width of the div tag is 100%
    • The default height fits the height of its content
  • flex-direction: row
    • The main axis corresponds to the width, so the content is divided over the full 100% width
    • The cross axis corresponds to the height, so every flex item is stretched to fill this height
  • flex-direction: column
    • The main axis corresponds to the height, so the content is divided over this height
    • The cross axis corresponds to the width, so every flex item is stretched to the full 100% width
  • If you explicitly set the width and height of the flex container, you get this result:

 
 




.parent {
    width: 200px;
    height: 200px;
    display: flex;
    ...
}
1
2
3
4
5
6

REMARK 3

  • Until now, we never set width/height on the flex ITEMS
    • These properties can also be used to influence the lay-out
    • You can, for example, add these properties to make every flex item a square box with centered text:

 
 
 
 



.child {
    width: 2rem;
    height: 2rem;
    text-align: center;
    line-height: 1;
    ...
}
1
2
3
4
5
6
7

# align-items (cross axis)

  • align-items distributes all flex items along the cross axis (just like justify-content does for the main axis)
  • Some of the align-items values (flex-start, flex-end and center) react the same as the values for justify-content
  • The table below contains the most used (not all) values for this property
EMMET instruction result description
ai:s + TAB align-items: stretch; (default) all flex items are equally stretched on the cross axis
ai:fs + TAB align-items: flex-start; all flex items are placed towards the start of the cross axis
ai:fe + TAB align-items: flex-end; all flex items are placed towards the end of the cross axis
ai:c + TAB align-items: center; all flex items are placed around the center of the cross axis
ai:b + TAB align-items: baseline; all flex items are placed on the font baseline on the cross axis

REMARKS

  • The align-items property can be used when the flex-wrap property is set to wrap or to nowrap
    • In the example below we use flex-wrap: wrap; to illustrate the difference with the align-content property (that will be introduced further on)
  • To demonstrate one of the values (align-items: baseline;) we give the second and third flex item a different font-size

 
 
 









 



 


.parent {
    height: 20rem;
    display: flex;
    flex-flow: row wrap;
    ...
}
.child {
    padding: .5rem;
    border: 1px solid #4D9900;
    background-color: rgba(77, 153, 0, 0.2);
}

.child:nth-child(2) {
    font-size: 2rem;
}

.child:nth-child(3) {
    font-size: 1.5rem;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# Exercise

  • Try to predict what happens when you set (in the previous example):
    1. flex-flow: row nowrap;
    2. flex-flow: row wrap; and justify-content: center;
    3. flex-flow: row wrap; and justify-content: space-between;
    4. flex-flow: column wrap; and experiment with some values of justify-content
    5. ...

# align-content (multi line - cross axis)

WARNING: NEED TO KNOW

The align-content property ONLY WORKS if the flex-wrap attribute is set to wrap

  • align-content distributes all flex lines along the cross axis
  • Some of the align-content values (flex-start, flex-end, center, space-between, space-around and space-evenly) react the same as the values for justify-content
  • The table below contains the most used (not all) values for this property
EMMET instruction result description
ac:s + TAB align-content: stretch; (default) all flex lines are equally stretched on the cross axis
ac:fs + TAB align-content: flex-start; all flex lines are placed towards the start of the cross axis
ac:fe + TAB align-content: flex-end; all flex items are placed towards the end of the cross axis
ac:c + TAB align-content: center; all flex items are placed around the center of the cross axis
ac:sb + TAB align-content: space-between; distribute all flex items evenly on the cross axis
(the first flex line is placed at the start of the cross axis,
the last flex line is placed at the end of the cross axis)
ac:sa + TAB align-content: space-around; distribute all flex items evenly on the cross axis
(flex lines have a half-size space on either end)
align-content: space-evenly; distribute all flex items evenly on the cross axis
(flex lines have an equal space between them)

REMARK: DIFFERENCE BETWEEN ALIGN-ITEMS AND ALIGN-CONTENT

  • align-items positions FLEX ITEMS WITHIN ONE FLEX LINE on the cross axis
  • align-content determines how FLEX LINES are positioned on the cross axis align-items vs align-content

# Exercise

  • Try to predict what happens when you set (in the previous example):
    1. flex-flow: column wrap;
    2. flex-flow: column wrap; and justify-content: center;
    3. flex-flow: column wrap; and justify-content: space-evenly;
    4. ...

# Examples

  • For our first examples, we don't need any of the flex related properties on the flex item

# Perfectly centered text

  1. Set the parent element (article) as a flex container
  2. Set the height of the flex container to 100% of the viewport height
  3. Center the text on the main axis and on the cross axis

 
 
 
 



article {
    display: flex;
    height: 100vh;
    justify-content: center;
    align-items: center;
    background-image: linear-gradient(to bottom, #cbe25f, #7e8627);
}
1
2
3
4
5
6
7

This is an alternative for the line-height:100% that we've seen earlier in the course. Using flexbox has the added advantage that you can center every element (div, p, ...) instead of just one line of text.

# Perfectly centered, responsive image

  • The figure element has exactly the same flexbox properties as the article in the previous example

 
 
 
 



figure {
    display: flex;
    height: 100vh;
    justify-content: center;
    align-items: center;
    background: linear-gradient(to bottom right, #5A98BF, white);
}
1
2
3
4
5
6
7
  • To ensure that the image always falls within the viewport in both landscape mode and portrait mode, we set the height of the image to 80% of the SMALLEST dimension of the viewport (height: 80vmin)

 




img {
    height: 80vmin;
    border: 1px solid #000;
    box-shadow: 0 0 20px rgba(0, 0, 0, .6);
}
1
2
3
4
5

# Flex item (child)

# align-self (cross axis)

  • align-self can be used to overwrite the global align-items property for a specific item element
EMMET instruction result description
as:s + TAB align-self: stretch; item is stretched inside its flex line on the cross axis
as:fs + TAB align-self: flex-start; item is placed towards the start of its flex line on the cross axis
as:fe + TAB align-self: flex-end; item is placed towards the end of its flex line on the cross axis
as:c + TAB align-self: center; item is placed around the center of its flex line on the cross axis
as:b + TAB align-self: baseline; item is placed on the font baseline inside its flex line on the cross axis
  • In the example below:
    • The default alignment on the cross axis is flex-start


     
     
     
     



    .parent {
      height: 20rem;
      display: flex;
      flex-flow: row wrap;
      justify-content: space-around;
      align-items: flex-start;
      ...
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    • The second and the tenth item are centered on the cross axis


     



    .child:nth-child(2),
    .child:nth-child(10) {
        align-self: center;
        background-color: rgba(153, 47, 0, 0.2);
    }
    
    1
    2
    3
    4
    5
    • The third, seventh and last item are pushed to the end on the cross axis



     



    .child:nth-child(3),
    .child:nth-child(7),
    .child:last-child {
        align-self: flex-end;
        background-color: rgba(88, 0, 153, 0.2);
    }
    
    1
    2
    3
    4
    5
    6

# order (main axis)

  • By default, every item is ordered according to the position in the DOM and has an order value of 0
  • You can change the individual order of each item by giving the order property a positive or negative value
EMMET instruction result
ord + TAB order: ;
  • In the example below:
    • The default order on the main-axis is 0
    • The second and the tenth item have an order number of -1


     



    .child:nth-child(2),
    .child:nth-child(10) {
        order: -1;
        background-color: rgba(153, 47, 0, 0.2);
    }
    
    1
    2
    3
    4
    5
    • The third and the last item have an order number of 1


     



    .child:nth-child(3),
    .child:last-child {
        order: 1;
        background-color: rgba(88, 0, 153, 0.2);
    }
    
    1
    2
    3
    4
    5
    • The fifth item has an order number of 2

     



    .child:nth-child(5) {
      order: 2;
      background-color: rgba(0, 30, 153, 0.2);
    }
    
    1
    2
    3
    4

# flex-grow (main axis)

  • In the example below, all flex items have a fixed width of 3rem
  • Even if there is more space than 9rem (three items of 3rem) in the flex container, the items will not be wider than their original size
    • You can adjust this behavior via the flex-grow property
  • Every item has a default value of flex-grow: 0

Default flex-grow is 0

  • If you specify exactly one item with a value greater than 0, this item will take up all the remaining width

One item with flex-grow > 0

  • If you specify all items with the same value, but greater than 0, all items get an equal share of the remaining width

All item with the same flex-grow

  • If you specify different values for every item, you can calculate the share of each item
    • The first item has flex-grow: 2, the second item flex-grow: 4 and the last item flex-grow: 6
    • This is a total of 2 + 4 + 6 = 12
    • The first item get 2/12 of the remaining space, the second item gets 4/12 and the last item 6/12

All item with the different flex-grow

EMMET instruction result
fxg + TAB flex-grow: ;

# flex-shrink (single line - main axis)

  • In the example below, all flex items have a fixed width of 10rem and the flex container has a max-width of 23rem (minus the padding is 21rem for the content)
  • If there is not enough space for the flex items to fit in the flex container, the flex items will all shrink at the same rate by default
    • You can adjust this behavior via the flex-shrink property
  • Every item has a default value of flex-shrink: 1
  • So, 21rem / 3 items is 7rem per item
    • Note that you get the same result when you give all flex items the same flex-shrink value!

Default flex-shrink is 1

  • If you specify one or more items with a value of 0, these items will not shrink

item with flex-shrink is 0

  • You can also specify different values for every item
    • The first item has flex-shrink: 2, the second item flex-shrink: 4 and the last item flex-shrink: 6
    • The second item shrinks (4/2=) two times faster then the first item
    • The third item shrinks (6/2=) three times faster then the first item

All item with the different flex-shrink

EMMET instruction result
fxsh + TAB flex-shrink: ;

REMARK

  • flex-shrink has no effect with the setting flex-wrap: wrap; on the flex container because then a new row is automatically created if there is not enough room for the items
    • Look what happens when setting flex-wrap: wrap; in the example above
    • All flex items expand to their original width of 10rem



 



.parent {
    max-width: 23rem;
    display: flex;
    flex-wrap: wrap;
    ...
}
1
2
3
4
5
6

# flex-basis (main axis)

  • The flex-basis property sets the initial size of a flex item on the main axis
  • The default value for flex-basis is auto
  • If the normal size (width or height, depending on the direction) is also set, then a flex-basis property other than auto will overwrite these settings
    • If flex-direction: row then flex-basis overwrites the width property
    • If flex-direction: column then flex-basis overwrites the height property
  • The properties min-width, max-width, min-height and max-height can still be used and are not effected by flex-basis
  • In the first example, all flex items have only a width and a height of 3rem
  • In the second example, all flex items have also a width and a height of 3rem
    • the second item has a flex-basis of 5rem and overwrites width: 3rem;
    • the third item has a flex-basis of 10rem and overwrites width: 3rem;

Example with flex-basis of 100% Flex-Basis 1

Example with only the second div a flex-basis of 100% Flex-Basis 2

# Exercise

  • Change the flex-direction of the flex container to column and see how the flex-basis property now overwrites the height property instead of the width property
EMMET instruction result
fxb + TAB flex-basis: ;

# flex (shorthand)

  • Flex is just a shorthand for flex-grow, followed by flex-shrink and flex-basis
  • Some (common) examples:
flex flex-grow flex-shrink flex-basis
flex: 1 1 auto; 1 1 (default) auto (default)
flex: 0 1 3rem; 0 (default) 1 (default) 3rem

TIP

  • To avoid confusion, we advice to specify a value for all the properties (flex-grow, flex-shrink and flex-basis) involved. As such, it's convenient to know the default values of these properties (flex-grow: 0;, flex-shrink: 1;, flex-basis: auto;) by heart!
EMMET instruction result
fx + TAB flex: ;

# Examples

# Basic navbar

  • A basic navbar (without styling) requires only 5 lines of flex related properties
  • Just for demonstrating purposes, all relevant elements have an outline (ul is blue, li is green and a is red)
  1. Transform the unordered list to a flexbox and remove the bullets from the unordered list

 
 



nav ul {
    display: flex;
    list-style-type: none;
    outline: 1px solid #0066CC;
}
1
2
3
4
5

basic navbar step 1
2. Spread all list items equally along the main axis


 





nav li {
    flex: 1 1 auto;
    /* display: flex; */
    outline: 1px solid #7600cc;
    outline-offset: -2px;
}
1
2
3
4
5
6

basic navbar step 2
3. Make every list item a flex container and spread its child element (the anchor tag a) to its full width, such that it looks like the whole list item is clickable



 




 




nav li {
    flex: 1 1 auto;
    display: flex;
    outline: 1px solid #7600cc;
    outline-offset: -2px;
}
nav a {
    flex: 1 1 auto;
    outline: 1px solid #cc4b00;
    outline-offset: -4px;
}
1
2
3
4
5
6
7
8
9
10
11

basic navbar step 3

# Responsive navbar with styling

Responsive navbar

  1. Screen size < 400px
    • Show all list items in a column
    • The two li.spacer elements are not visible


     











     


    nav ul {
       display: flex;
       flex-direction: column;
       ...
    }
    nav li {
       display: flex;
       ...
    }
    nav a {
       flex: 1 1 auto;
       ...
    }
    nav li.spacer {
       display: none;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
  2. Screen size >= 400px and < 600px
    • Switch the orientation of the list items from column to row
    • Each list item must grow with the same amount so that they are equally distributed along the entire width
    • The content inside every anchor tag a is horizontally centered
    • Only the icon inside the anchor tag a is visible, the text is hidden
    • The link Q&A is moved to the far right of the navbar
    • The two li.spacer elements are (still) not visible


     


     


     


     


     



    @media screen and (min-width: 400px) {
        nav ul {
            flex-direction: row;
        }
        nav li {
            flex: 1 1 auto;
        }
        nav a {
            text-align: center;
        }
        nav a span {
            display: none;
        }
        .qa {
            order: 1;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
  3. Screen size >= 600px and < 800px
    • Make the two li.spacer visible and let them grow twice as fast as the other list items


     
     



    @media screen and (min-width: 600px) {
        nav li.spacer {
            display: block;
            flex: 2 1 auto;
        }
    }
    
    1
    2
    3
    4
    5
    6
  4. Screen size >= 800px
    • Hide the two li.spacer elements again
    • Show the text on the right side of every icon


     


     



    @media screen and (min-width: 800px) {
        nav li.spacer {
            display: none;
        }
        nav a span {
            display: inline;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8

REMARK

In this example, we use Font Awesome icons, which will be discussed in detail in the follow-up course Webdesign advanced. For now, it suffices to know that

  • you have to import the icon library by using an @import statement in your CSS-file, just as we did for Google fonts: @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css');
  • you can use the 1609 free icons by putting them in an i-tag in your HTML file: <i class="fas fa-home"></i>

# Full page layout

Full page layout

  • All the flex magic happens inside the main container
  • Small screen
    • nav, section and aside are positioned below each other

 
 


main {
    display: flex;
    flex-direction: column;
}
1
2
3
4
  • Large screen
    • nav, section and aside are positioned next to each other
    • nav and aside have a fixed width of 150px
    • The section takes the rest of the space with a left and right margin of 1rem


 


 


 
 
 



@media screen and (min-width: 600px) {
    main {
        flex-direction: row;
    }
    nav, aside {
        flex: 0 1 150px;
    }
    section {
        flex: 1 1 auto;
        margin-left: 1rem;
        margin-right: 1rem;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# Dices

  • Try to understand how these dices are constructed
  • In this example, we have chosen not to fully optimise the code, but to code the flexbox properties per dice
  • A little exercise: change the orientation of dice 3 and dice 6
    rotate dices
Last Updated: 9/10/2023, 2:54:38 PM