Create your account

Already have an account? Login here

Note: By joining, you will receive periodic emails from Coursetro. You can unsubscribe from these emails.

Create account

Using CSS Flexbox for Vertical Positioning & Alignment

By Gary simon - Aug 15, 2017

I took it upon myself to start a new app which required a rather unique layout, as compared to a typical website landing page. This app required a variety of positioning, mainly vertical positioning, across various elements.

In this tutorial, I'm going to recreate the general layout and show you how it all works with CSS Flexbox. So let's get started!

We have some pretty awesome courses

Check them out

If you prefer to watch a tutorial

Be sure to Subscribe to the Official Coursetro Youtube Channel for more awesome videos!

Starting the Project

Because this is solely a CSS tutorial, I'm not going to bother with setting up some sort of robust development environment with unnecessary bells and whistles. Instead, we're just going to create 2 files in a single folder.

Using your preferred code editor, create a file named index.html and paste in the following contents:

<html lang="en">
<head>
  <meta charset="utf-8">
  <title>CSS Flexbox Tutorial</title>

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="style.css">
</head>
<body>

</body>
</html>

Next, create a style.css in the same folder, and for now we'll keep it empty.

Defining a 2 Column Flexbox Layout

Our layout, at least initially, is going to consist of 2 columns. I'm not going to bother using a CSS framework for this. Instead, we're going to keep everything simple and custom.

In the index.html file, within the body tags, add the following:

    <div class="sidebar">

    </div>
    <div class="content">

    </div>

In our style.css file, let's reference both of these new classes, along with the body element:

body {
    margin:0;
    font-family: Arial, Helvetica, sans-serif;
    display:flex;
    flex-direction: row;
}

.sidebar {
    background:gray;
    width: 15%;
    padding:1em;
}

.content {
    background:lightgray;
    width: 85%;
}

Here, we're defining the default body element as the flexbox container with:

  • display: flex;
    This makes it a flexbox container.
  • flex-direction: row;
    This means any children within the body tag, situated in rows, as opposed to columns (column being the other value).

If we visit index.html in the browser, you'll see a similar result:

Notice how the height of the columns fills the browser viewport? What if we wanted to add a horizontal navigation header above these columns. Will it still work? Will we get unwanted vertical scrolling? Let's try.

Adding to the index.html file:

  <header>
    <ul>
      <li><a href="#">About us</a></li>
      <li><a href="#">Services</a></li>
      <li><a href="#">Contact</a></li>
    </ul>
  </header>

  <div class="sidebar">

  </div>
  <div class="content">

  </div>

And in the browser, the result is this:

Ugh, that's not what we want! This is happening because it's a child of body, which will align all children as a row.

To fix this, we have to modify our HTML and CSS a little bit.

index.html:

  <header>
    <ul>
      <li><a href="#">About us</a></li>
      <li><a href="#">Services</a></li>
      <li><a href="#">Contact</a></li>
    </ul>
  </header>
  <div class="wrapper">
    <div class="sidebar">

    </div>
    <div class="content">

    </div>
  </div>

Here, we've added a wrapper class around the sidebar and content class. This will allow us to move the flex properties from the body element to the wrapper class. 

style.css:

body {
    margin:0;
    font-family: Arial, Helvetica, sans-serif;
}

.wrapper {
    display:flex;
    flex-direction: row;
}

.sidebar {
    background:gray;
    width: 15%;
    padding:1em;
}

.content {
    background:lightgray;
    width: 85%;
}

/* Menu styling */

ul {
    list-style-type:none;
    margin:0;padding:0;
    display:flex;
    flex-direction:row;
    justify-content: flex-end;
}

ul li a {
    padding: 20px;
    display:block;
}

Save and refresh the browser:

Why are the columns no longer extending to the bottom of the browser? We need to define a height on the wrapper class. So, modifying just the wrapper ruleset, add the height property:

.wrapper {
    display:flex;
    flex-direction: row;
    height: 100vh;         /* Add this */
}

vh is a unit for Viewport Height. Refresh the browser:

Now, we have an unwanted vertical scroll bar. This is because we must subtract the height of the header element from the height property of .wrapper:

.wrapper {
    display:flex;
    flex-direction: row;
    height: calc(100vh - 60px);
}

/* Add this ruleset to define a height on the header /*

header {
    height:60px;
}

Now to refresh:

Vertical Positioning with Flexbox

Let's say for example that this is a chat app. In the .content container, we want to add an element to display chat messages, and at the very bottom, always aligned to the bottom of the viewport, will go a text input.

Let's modify index.html:

    <div class="content">
      <div id="chat-container">
        <div id="chat">
          <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. </p>
        </div>
        <input type="text" placeholder="Chat here">
      </div>
    </div>

We've added 2 div's with #chat-container and #chat. These two divs are children of chat-container, which will be a necessary element when it concerns positioning these 2 divs correctly.

As it stands, the result looks like this:

Ugly, so let's fix that. In our CSS file, add the following 3 rulesets:

#chat-container {
    flex-direction: column;
    display:flex;
    min-height: 100%;
    color:gray;
}

#chat {
    width:100%;
    flex: 1;
    overflow-y: scroll;
    padding: 30px;
    box-sizing: border-box;
}

input[type="text"] {
    width: 100%;
    padding: 10px;
}

We make #chat-container a new flex container, and we set the flex-direction to column this time. That's because we're vertically stacking the chat messages and then the input.

Then, we reference #chat and give it the property of flex: 1; This means let all of the flex items be the same length. Since we're only applying it to one of the two children (not the input), it will take up the entire space minus the height of the input.

If we were to add flex: 1; to the input ruleset, it would accompany 50% of the height, which we don't want.

This is the result in the browser based on the above rulesets being added:

Final Words

Hopefully you were able to learn some basics of CSS flexbox positioning. If you followed along, you will have noticed we didn't use any floating. Flexbox can be a bit tricky at first, but as with everything, it just takes some time, patience and repitition to understand.

See you next time!

 

 


Share this post




Say something about this awesome post!