AV's Blog

CSS Layout and Flexbox Exercise

August 13, 2018

I just went through an exercise from my past on flexbox and CSS. I thought it would be a good review for me to write about it here so I can remember what I’ve done.

The exercise involves writing some CSS rules as well as JavaScript to come up with a landing page for a fictitious website called “Aviatto”. The following shows the desired appearance of the landing page:

objective

I will not write the original html file that was given but will write some snippets. The given html file, however, already had some default CSS styles such as the font-family, and some background color for some elements.

About Section

Instead of tackling the navigator and the ‘hero’ first, the exercise dealt immediately with flexbox usage on the “About” section. This contains a paragraph on the left, and an image on the right.

<section id="about">
    <h2>About</h2>
    <div>
      <p>
        Aviatto is a Paradigm shift app for Long tail ... (ommitted for brevity)
      </p>
      <div id="aboutmockup">
        <img src="images/mockup.png" alt="App mockup" />
      </div>
    </div>
  </section>

Since we need elements p and the div with id ‘aboutmockup’ in a row, we need to target their parent div (the one below the h2 element containing the text ‘About’). To do this, we use the descendant CSS combinator or selector, which we can safely use because there aren’t any other divs in the same level.

#about div {
  display: flex;
}

This results to the p and div with an id of aboutmockup default to a flex-direction of row.

about1before becomes about1

To appropriately distribute the space between p and div, we can use the child property flex, which is a combination of flex-grow, flex-shrink, and flex-basis. For more information on the property flex, check out this site. Looking at the We then target these two elements like so:

#about p {
  flex: 3;
  margin-left: 1em;
}

#about #aboutmockup {
  flex: 2;
  margin-right: 1em;
}

Adding margins on the right and the left of the elements, we get:

flex

Staff Section

Next, we tackle the “Staff” section. Initially, all the divs under staff are on top of each other.

staff initial

To get these in the desired arrangement of three on each row, we again use flexbox. In this case, we need to target the first div in the section with id “staff” (see arrow).

<section id="staff">
    <h2>Staff:</h2>
 ->  <div>
      <div class="staff-profile">
        <i class="em em-angry headshot"></i>
        <h3 class="staff-name">Operations Ollie</h3>
        <p class="staff-bio">While not leading our Operations team, Ollie is busy entertaining his life's true passion: Ice Fishing.
        </p>
      </div>
     /* four divs omitted for brevity */
      <div class="staff-profile">
        <i class="em em-grin headshot"></i>
        <h3 class="staff-name">Executive Ellie</h3>
        <p class="staff-bio">Ellie dropped out of Princeton during her junior year at age 17. Yes, she will bring this up every chance she gets.
        </p>
      </div>
    </div>
  </section>

To do this, we use the “child CSS combinator”. We give it a property display with a value of flex.

To make the divs go in one row, the property, we give it property flex-wrap and value wrap (or flex-flow: row wrap. We also give it the appropriate margin.

#staff > div {
  display: flex;
  flex-wrap: wrap;
  margin: 0 1em;
}

This doesn’t look like it did anything though, because each flex item occupies the maximum width of the flex container.

flexwrap staff

So we again resort to the flexbox child property flex. The child element we want to select is the div with a class name of “staff-profile”. We then use the class CSS selector. We want to give it a flex-basis value of 33% (100% of the width divided by 3).

.staff-profile {
  flex: 0 0 33%; /* or flex-basis: 33% */
}

Each of the “staff-profile” divs are now aligned as desired.

flex staff

Next, we want to center all the contents inside the “staff-profile” divs. It’s actually a lot easier doing this using flexbox. We can make the div a flex container, and center all the children using align-items (instead of justify-content), and also using flex-direction with value column (using display: flex defaults to a flex-direction of row).

.staff-profile {
  flex: 0 0 33%;
  display: flex;
  flex-direction: column;
  align-items: center;
}

After this, we can see that the children elements are centered. But inside the “staff-bio” p element, the text is not centered. We can use the text-align property for this. We also add a margin.

.staff-bio {
  text-align: center;
  margin: 1.5em;
}

center staff

Lastly, it looks like we need to increase the size of the icons. I resorted to increasing the width and height of the element i using the class name “headshot” using viewport sizes.

.headshot {
  width: 6vw;
  height: 6vh;
  margin-top: 1em;
}

headshot icons

Header

The header desired is actually a “sticky” header. But before doing that, we needed to do more flexboxing.

header orig

<header>
    <div class="logo">
      <img alt="logo" src="images/logo.png" />
    </div>
    <nav>
      <div class="nav-item">
        <a href="#">About</a>
      </div>
      <div class="nav-item">
        <a href="#">Features</a>
      </div>
      <div class="nav-item">
        <a href="#">Careers</a>
      </div>
    </nav>
  </header>

We want the “logo” and the nav to be at the same row. We also want the nav-items to be in the same row.

So we make header and nav flex containers. To the children nav and “logo”, we add the flex property and give them values 3 and 1. To the nav element, we add justify-content and give a margin on the right.

header {
  header {
  background-color: rgba(37, 37, 37, 0.8); /* default rule */
  display: flex;
}

.logo {
  flex: 3;
}

nav {
  flex: 1;
  display: flex;
  justify-content: space-between;
  margin-right: 1em;
}

header flex

Next, remove the underlines, increase the font-size, and change the color to white, center vertically, fix the spacing even more, for the nav-items. For the “logo”, change the size, center vertically, and add margins.

After all these, the css rules now look like this:

header {
  background-color: rgba(37, 37, 37, 0.8);
  display: flex;
  padding: 0.5em 1em;
  border-radius: 0 0 15px 15px;
  width: 90%;
  margin: 0 auto;
  align-items: center;
}

nav {
  flex: 1;
  display: flex;
  justify-content: flex-start;
}

.logo {
  flex: 3;
  display: flex;
  align-items: center;
}

.logo img {
  width: 30%;
}

.nav-item {
  flex-basis: 33%;
}

.nav-item a {
  color: #fff;
  text-decoration: none;
  font-size: 2vw;
}

This gives the following result:

header formatted

Note that I played around with justify-content and flex-basis to change the spacing of the nav-items.

Next, to make the header sticky (disappears when scrolled up and appears when scrolling down), we add the following properties to header:

header {
  /* previous rules omitted */
  position: fixed;
  z-index: 2;
  left: 5%;
}

This makes the header able to stay on top of the screen. The position property of value fixed will make the element stay put on the screen, while z-index makes it stack on top of the next element (the section with id “carousel”). The left property adjusts it horizontally along the screen. For more info on the position property, here is an article.

via GIPHY

Carousel Section

We’re almost done. The next step is to fix the carousel section. We only need to fix the positioning of two elements so that they are on top of each other.

<section id="carousel">
  <div id="carousel-text">
    <h1>Aviatto: Traveling for a better world</h1>
    <h2>Learn More</h2>
  </div>
  <img class="carousel-image" src="images/bg/mountains.jpg" />
</section>

The div with id “carousel-text” and img element should be stacked, and the text centered appropriately. How do we do this?

We use the position property again on the div with id “carousel-text” and adjust its horizontal and vertical positions using the left and top property.

#carousel-text {
  position: absolute;
  left: 25%;
  top: 25%;
}

Before: carousel before

After: carousel after

We now have a properly styled landing page! But we can add more to improve it. I’ll go over that in the future. But this is it for now.