CSS106 - Flex and Float

Flex is a powerful new tool that helps make it easier to position items intuitively within a parent container. Its purpose is to distribute space along a single column or row and the elements within it.

Big Important Note

It is the third iteration of the specification for flex. This means if you find any articles with anything other than display: flex (e.g. display: flexbox or display: box) they are following different specifications and the behaviour will be different.
  1. The Basics


    The above diagram includes the terminology that we'll be using while studying flex. The first thing to note is that you only need to set the parent element to display: flex to make its children flex-items.
    .parent
      #child1 1
      #child2 2
      #child3 3
    .parent
      display: flex
    1
    2
    3

    Out of the box this does a couple of things. It keeps all the items in source order but also makes sure they all fit on the same row. If this cannot be accomplished it shrinks the divs equally. The child elements also expand to fit the parent when the height is not set.

    Flex direction

    There are 4 flex-directions that can be set: row/row-reverse/column/column-reverse. It defines which direction the main parent element aligns its children in. Row is left to right on the main-axis, while row-reverse is from right to left on the main axis. Column is top to bottom on the cross-axis, and column reverse is bottom to top on the cross-axis.
    .parent
      #child1 1
      #child2 2
      #child3 3
    .parent
      display: flex
      flex-direction: column
    1
    2
    3

    .parent
      #child1 1
      #child2 2
      #child3 3
    .parent
      display: flex
      flex-direction: row-reverse
    1
    2
    3

    Flex-wrap


    Apart from flex-direction we have flex-wrap. The default is nowrap which means that the flex element will try and fit all its children in one line. Seeing flex-wrap to wrap will allow elements to flow onto the next line. Wrap-reverse flows elements onto the next line but displays them in opposite order.

    flex-wrap: nowrap

    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      flex-wrap: nowrap
    1
    2
    3
    4

    flex-wrap: wrap

    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      flex-wrap: wrap
    1
    2
    3
    4

    flex-wrap: wrap-reverse

    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      flex-wrap: wrap-reverse
    1
    2
    3
    4

    Flex-flow


    flex-flow allows us to set both flex-direction and flex-wrap in one element as flex-flow:
    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      flex-flow: row-reverse wrap-reverse
    1
    2
    3
    4
  2. Aligning content

    There are three attributes used to align content: justify-content, align-items and align-content.

    Justify-content

    Justify-content distributes the extra space along the main-axis for a row or the cross-axis for a column. It has 5 potential values: flex-start, flex-end, center, space-between, space-around. The default is flex-start. Flex-start and flex-end place the items as close as possible to the axis start and the axis end respectively. Center places them in the middle. Space-between maximises the space between them and space-around equally distributes the remaining space to the left and right of each element.
    .parent
      #child1 1
      #child2 2
      #child3 3
    .parent
      display: flex
      justify-content: flex-start
    1
    2
    3

    Justify-content: center

    .parent
      #child1 1
      #child2 2
      #child3 3
    .parent
      display: flex
      justify-content: center
    1
    2
    3

    Justify-content: flex-end

    .parent
      #child1 1
      #child2 2
      #child3 3
    .parent
      display: flex
      justify-content: flex-end
    1
    2
    3

    Justify-content: space-between

    .parent
      #child1 1
      #child2 2
      #child3 3
    .parent
      display: flex
      justify-content: space-between
    1
    2
    3

    Justify-content: space-around

    Note that with space-around each element has the same amount of space to the left and right of it. The space between 1 and 2 and 2 and 3 looks bigger than the space between 1 and the start and 3 and the end because both the right space of 1 and 2 stack on top of the left space of 2 and 3.
    .parent
      #child1 1
      #child2 2
      #child3 3
    .parent
      display: flex
      justify-content: space-around
    1
    2
    3

    Align-items

    align-items does the same as justify-content but along the cross axis for a row and the main axis for a column. It can be set with stretch, flex-start, flex-end and center. These operate in the same way as the justify-content settings except that stretch stretches the child elements to fit to the parent-elements height. This only works if no height has been set for the child elements.

    Align-items: stretch

    .parent
      #child1 1
      #child2 2
      #child3 3
    .parent
      display: flex
      align-items: stretch
      height: 100px;
    1
    2
    3

    Align-items: flex-start

    .parent
      #child1 1
      #child2 2
      #child3 3
    .parent
      display: flex
      align-items: flex-start
      height: 100px;
    1
    2
    3

    Align-items: flex-end

    .parent
      #child1 1
      #child2 2
      #child3 3
    .parent
      display: flex
      align-items: flex-end
      height: 100px;
    1
    2
    3

    Align-items: center

    .parent
      #child1 1
      #child2 2
      #child3 3
    .parent
      display: flex
      align-items: center
      height: 100px;
    1
    2
    3

    Align-content

    Lastly align-content aligns items along the cross-axis but on a row by row basis for a row or on the main axis by a column by column basis for a column. It has exactly the same options as justify-content, but affects each row rather than each element.
    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      align-content: stretch
      flex-flow: row wrap
    1
    2
    3
    4

    Align-content: flex-start

    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      align-content: flex-start
      flex-flow: row wrap
    1
    2
    3
    4

    Align-content: flex-end

    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      align-content: flex-end
      flex-flow: row wrap
    1
    2
    3
    4

    Align-content: space-between

    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      align-content: space-between
      flex-flow: row wrap
    1
    2
    3
    4

    Align-content: space-around

    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      align-content: space-around
      flex-flow: row wrap
    1
    2
    3
    4
  3. Flex-items

    The child elements themselves can also be given specific properties.
    By default the child elements will be ordered in the order of the source. However their order can specifically be set with the order attribute.
    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      flex-flow: row
    #child1
      order: 3
    #child2
      order: 1
    #child3
      order: -1
    #child4
      order: 0
    1
    2
    3
    4

    Flex-grow and flex-shrink define the rate at which the element grows and shrinks when the full width/height of the row/column has been reached.

    Flex-grow

    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      flex-flow: row
    #child1
      flex-grow: 1
    #child2
      flex-grow: 2
    #child3
      flex-grow: 3
    #child4
      flex-grow: 1
    1
    2
    3
    4

    Flex-shrink

    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      flex-flow: row
    #child1
      width: 500px
      flex-shrink: 1
    #child2
      width: 500px
      flex-shrink: 2
    #child3
      width: 500px
      flex-shrink: 3
    #child4
      width: 500px
      flex-shrink: 1
    1
    2
    3
    4

    Flex-basis

    Flex-basis is used so that elements have a starting size. If the direction is a column then this will set the height of the items, otherwise it will set the width.
    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      flex-flow: row
      justify-content: center
    #child1
      flex-basis: 150px
    #child2
      flex-basis: 150px
    #child3
      flex-basis: 150px
    #child4
      flex-basis: 150px
    1
    2
    3
    4

    Flex-basis as column

    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      flex-flow: column
      justify-content: center
    #child1
      flex-basis: 150px
    #child2
      flex-basis: 150px
    #child3
      flex-basis: 150px
    #child4
      flex-basis: 150px
    1
    2
    3
    4

    Flex shorthand

    Flex is the shorthand for flex-grow, flex-shrink, flex-basis. This allows one attribute to be set for all 3.
    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      flex-flow: row
      justify-content: center
    #child1
      flex: 0 0 150px
    #child2
      flex: 0 1 150px
    #child3
      flex: 1 0 150px
    #child4
      flex: 1 1 150px
    1
    2
    3
    4

    Align-self

    Lastly an individual item can override the align-items set through align-self. This has the same options as align-items, but only changes the individual item.
    .parent
      #child1 1
      #child2 2
      #child3 3
      #child4 4
    .parent
      display: flex
      flex-flow: row
      justify-content: space-around
      align-items: center
    #child1
      flex: 0 1 150px
    #child2
      flex: 0 1 150px
      align-self: flex-start
    #child3
      flex: 0 1 150px
    #child4
      flex: 0 1 150px
    1
    2
    3
    4
  4. Float

    Float is an attribute that used to be used for situations that flex now resolves. It may still be found in some code today and as it is older is supported by more browsers. For prototyping though flexbox is better to use as it makes making complex layouts easier. Float shifts content to the left or right depending on the settings.
    .parent
      #child1 1
      #child2 2
    #child1
      float: right
    #child2
      float: left
    1
    2
  5. Exercises

      • Set up a new folder with the appropriate files and create 3 flex parent elements of 700px x 400px.
      • Give the first parent 8 children of 150px x 100px and display them in two rows. There should be even spacing between each element within a row. One row should appear at the top of the parent element and the other should be at the bottom.
      • Give the second parent 8 children of 90px x 100px and display them in two columns. There should be even spacing between each element within a column. The two columns should also have equal spacing between them and the start and the end of parent.
      • Give the third parent 1 child of 100px x 100px and place it both vertically and horizontally in the center.

      In the end your page should look something like this. Use the inspect tool if you are stuck or to check your answers.
      link(href='style.styl' rel='stylesheet')
      
      .parent#par1
        .child
        .child
        .child
        .child
        .child
        .child
        .child
        .child
      
      .parent#par2
        .child
        .child
        .child
        .child
        .child
        .child
        .child
        .child
      
      .parent#par3
        .child
      body
        background-color: black
      
      .parent
        display: flex
        background-color: yellow
        height: 400px
        width: 700px
        margin: 0px auto 20px auto
      
      .child
        background-color: #FF8B00
      
      #par1
        justify-content: space-around
        align-content: space-between
        flex-flow: row wrap
        .child
          height: 100px
          width: 150px
      
      #par2
        justify-content: space-around
        align-content: space-around
        flex-flow: column wrap
        .child
          height: 90px
          width: 100px
      
      #par3
        justify-content: center
        align-items: center
        flex-flow: row
        .child
          height: 100px
          width: 100px

    1. Recreate this page. Use the akcolor.styl stylesheet. Avoid using the inspect tool until you are finished and then use it to check your answer.
    2. link(href='style.styl' rel='stylesheet')
      
      .navbar
        .left ^_^ The Smiley Company
        .right About | Blog | Contact
      
      .content
        #first
          | Be not afraid of greatness: some are born great, some achieve greatness, and some have greatness thrust upon them.
        #second
          | To thine own self be true, and it must follow, as the night the day, thou canst not then be false to any man.
        #third
          .center
            .item
              img(src="https://upload.wikimedia.org/wikipedia/commons/thumb/4/42/Love_Heart_SVG.svg/847px-Love_Heart_SVG.svg.png")
          | The course of true love never did run smooth.
      
      .footer
        .link Contact | Content Map | About
      @require "akcolor.styl"
      
      body
        margin: 0
        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif
      
      .navbar
        background-color: $ak-color-Y75
        height: 60px
        display: flex
        justify-content: space-between
        line-height: 60px
        .left, .right
          background-color: $ak-color-Y100
          padding: 0 20px
      
      .content
        display: flex
        justify-content: space-around
        align-items: center
        height: 120vh
        #first, #second, #third
          height: 100vh
          background-color: $ak-color-Y100
          flex: 0 1 400px
          padding: 20px
      .center
        display: flex
        border: 5px solid $ak-color-R100
        justify-content: center
        height: 400px
        align-items: center
        margin-bottom: 20px
        .item
          img
            width: 300px
      
      .footer
        background-color: $ak-color-Y75
        height: 60px
        display: flex
        justify-content: center
        align-items: center
        .link
          margin-left: 20px

    3. Look at typography.sketch, http://proto.office.atlassian.com/adgHome/ and dropdown.sketch and discuss if/how you would use flex to create it.
    4. If you want some extra practice that will help the different commands stick in your brain check out the flex-box zombie game and the froggy game.