How to create a vertical banner layout

Posted by Vernon Joyce
January 23, 2017

Have you ever seen a beautiful piece of work by an Awwwards winner and wondered just how they managed to pull it off? Welcome to the first in the How it’s built series. How it’s built focusses on deconstructing popular web widgets, digital design pieces and more, in our easy to understand step-by-step guides. I will guide you through the code or software required to pull it off and apply it to your own project – our first project being How to create a vertical banner layout.

How it’s built will be available with source code as well as demos to make it easier to follow along. With that said, please remember that knowledge is power, and in this case the power lies in applying these techniques in your own original way. As a designer, plagiarism is the ultimate act of treason and you WILL walk the shaky plank that leads to the death of your career. Also know that although code is open source and can be implemented in your personal projects, that it’s best to give credit where credit is due, even if it’s just commented into your code.

What we’re building

To kick off How it’s built, we’ll be looking at the vertical banner layout used on Uncharted Waters. This effect is really simple to pull off and uses a trick a lot of junior developers don’t know about. This simple layout can add a much needed final touch to your homepage, and the best part is that it only requires 50 lines of CSS. This tutorial is for beginners, which means that I will explain some CSS concepts in depth. If you are confident in your CSS ability, simply have a look at the demo and read some key points from this article.

To understand how this effect works we need to think back to when the web was just starting out, and a web page took 15 minutes to load. Back then websites were all built with tables, using table rows and table cells. At this time, it was the best way to structure elements on a page effectively. Thankfully, the web has come a long way since then, and we now use a combination of different CSS properties to position elements on a web page.

With that said, we will in a sense be going back to the stone age for this tutorial by using table display properties in CSS. It is important to understand the difference: we will not be building actual HTML tables (using the <table> tag), we will be using block HTML containers with CSS display properties.

Getting Started

Let’s start off by creating a div container for our banners with a class of banner-container. Inside of the container, we will then add four more div containers for our individual banners with a class of banner. Lastly, add a background image to your banners using inline styling. You can alternatively also add a class or id to each of your banners and apply the background image to it via a CSS stylesheet:

<div class="banners-container">
  <div class="banner" style="background-image: url(img/bg-1.jpg);">
  </div>
  <div class="banner" style="background-image: url(img/bg-2.jpg);">
  </div>
  <div class="banner" style="background-image: url(img/bg-3.jpg);">
  </div>
  <div class="banner" style="background-image: url(img/bg-4.jpg);">
  </div>
</div>

Creating our table and table cell layout

What we want to do is assign CSS properties to our divs to treat them as if they are tables and table cells. Think of banners-container as the table and banner as the table cell. If you look at our example you will see that we essentially have a table with four columns. Because we aren’t building an actual HTML table we don’t need to add a table row, as our goal is to only use table and table cell properties.

To get our divs to act like tables and table cells, let’s start by adding display properties via CSS to banner-container and banner. The CSS display property tells the browser how an element should be displayed or interpreted. By default a div is set to display as a block level element. Using the CSS display property we are able to force banner-container to be treated as if it was a table and banner to be treated as a table cell. We can do this by adding the following CSS properties to our CSS file:

.banners-container {
  display: table;
}
.banners-container .banner {
  display: table-cell;
}

Setting the width and heights of our table and table cells

By default our table has no height or width. This is because currently our table does not have any actual content (such as text) to force it to have specific dimensions. Because of this we need to set a width and height for our table element. We will be setting both these properties to a 100% because we want our table to fill our viewport in width and height.

When it comes to the web, it is important to remember that a 100% width and height means that it is measured as a 100% of its parent element. This means that in order for our banners-container table to fill the viewport, our parent element needs to fill the viewport as well. Think about for a second: If you have a block that has a width of 600px and inside it, you have a block width a width of a 100%, in essence our inside block will also have a width of 600px as it is 100% of its parent.

Since our banners-container div is inside of our body HTML tag (in other words, its parent is <body>) we need to give a width and height to body as well. And since our body tag is inside of an html tag, we ultimately need to give our <html> tag a width and a height as well. We will also remove all the default paddings and margins from both html and body to ensure there aren’t any unwanted spaces around our banners.

Secondly, we want our banner strips to also have widths and heights. As with our banners-container table our banner won’t by default have a width or height, so we need to set this explicitly. The only exception here is that our banner table-cell will only have a 25% width. This is because we have 4 banners, and they need to be distributed within our table equally. If you have more or less banners in your design you can change 25% to whatever fraction of a 100% you want your banners to be.

With this in mind, our CSS will now look like this:

html, body {
  height: 100%;
  width: 100%;
}
.banners-container {
  display: table;
  width: 100%;
  height: 100%;
}
.banners-container .banner {
  display: table-cell;
  height: 100%;
  width: 25%;
}

Setting up our backgrounds and banners-container table

Save and check out the demo in your browser. You should now see our layout coming together. The next step is to make sure our background images stay in the middle when we hover over our blocks. We can do this by setting the background-size property of banner to cover and the background-position to center. Our background size property will essentially force the image to always fill the space available (so it “covers” our banner div) and the center position anchors the image to the middle of the banner div.

In order for this effect to work properly, you need to ensure that your background images are wide enough. If your banner div changes its width from 25% to for example 50%, your background will still try to cover the entire block. If your background image is not large enough to fit into the 50% background at its normal size, it will try to cover banner and as a result you will notice your background image scaling up.

We also need to add another special table property to our banners-container div to force it to have a fixed table layout. This property basically tells the browser that the width of this table is not allowed to be influenced by what is inside of it. Basically, it ensures that whenever one of our banner table cells resize, that our table’s width will remain exactly as it is. This is what our CSS looks like now:

html, body {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
}
.banners-container {
  display: table;
  width: 100%;
  height: 100%;
  table-layout: fixed;
}
.banners-container .banner {
  display: table-cell;
  height: 100%;
  width: 25%;
  background-size: cover;
  background-position: center;
}

Adding our first hover effects and animations

Next, let’s work on our actual effect by adding some CSS animations and hover properties. If you hover over banners in our demo, you will notice that we have two things happening:Firstly, the banner that is hovered over, expands in size. Secondly, all of the banners that are not hovered over are faded out.

Let’s start of by creating our hover effect for the selected banner. We can do this simply by adding a CSS :hover selector to our .banner class. To increase the size of the banner when it is being hovered over, simply change the width of the banner to 50% within our :hover selector. Because our banners-container div has a table layout of fixed, our banners will automatically resize to accommodate the larger, hovered one. Let’s also add some CSS animations to our banner by using the CSS transition property. CSS transitions allow us to animate items using only CSS. You can animate height, width, opacity, scale and much more. If you are unfamiliar with how CSS transitions work, use this generator to generate your transitions for you. In our case we will be animating all properties for 300 milliseconds with a basic ease.

html, body {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
}
.banners-container {
  display: table;
  width: 100%;
  height: 100%;
  table-layout: fixed;
}
.banners-container .banner {
  display: table-cell;
  height: 100%;
  width: 25%;
  background-size: cover;
  background-position: center center;
  -webkit-transition: all 300ms ease;
  -moz-transition: all 300ms ease;
  -ms-transition: all 300ms ease;
  -o-transition: all 300ms ease;
  transition: all 300ms ease; 
}
/* This is our hover selector */
.banners-container .banner:hover {
  width: 50%;
}

Adding our second hover effect for opacity

Run your code in a browser and make sure our hover selector is resizing is your banners correctly. Spiffy, ain’t it? You will notice that because all of the banners are equally bright and visible that they detract a lot of attention from the our hovered banner. To solve this we want to fade out the banners that aren’t being hovered over, and we can do this simply by lower their opacity. There are a couple of ways you can do this, but I will show you my technique.

We are going to first off add a :hover selector to our banners-container. What we want to do is to lower the opacity of all our banners whenever our banners-container is hovered over. The reason we are doing this is because we only want the opacity effect to trigger when we are actually interacting with our vertical banner layout. We can achieve this by doing the following:

.banners-container:hover .banner {
  opacity: 0.3; 
}

The above code basically just tells the browser, whenever banners-container is hovered, that all of the banners inside of it needs to have 0.3 opacity. This however will cause all of our banners to go transparent. To correct this issue, we simply make the opacity of the hovered banner 1:

.banners-container .banner:hover {
  width: 50%;
  opacity: 1; 
}

So to recap, we lower the opacity of our banners to 0.3 when we hover over banners-container and then we set the opacity of the actual banner that is hovered, back to 1.

Final touches

Now that our hover effects have been added, we can add a couple of final touches.

To start off with, I added another element inside our banners for the text that needs to fit inside each banner called banner-copy which contains a heading and a sub-heading. This is positioned absolutely and sits 80px from the bottom of our banners. You can also add a fixed width to banner-copy if your text is shifting around when your banner resizes. Because I used only two short lines you won’t notice this effect immediately.

If you want to make this layout work for mobile, you will need to change your banners to be 100% width and 25%. This will essentially turn the layout on its side. However, because of table layout fixed, your banners will still try and fit next to each other. You can fix this by simply setting our banner class to display: block once it reaches a mobile size. For more information on doing responsive layouts using media queries, click here.

The final HTML
<div class="banners-container">
  <article class="banner" style="background-image: url(img/bg-1.jpg);">
    <section class="banner-copy">
      <h1>Starry nights</h1>
      <h5>and wine with friends</h5>
    </section>
  </article>
  <article class="banner" style="background-image: url(img/bg-2.jpg);">
    <section class="banner-copy">
      <h1>Stunning vistas</h1>
      <h5>and great hikes</h5>
    </section>
  </article>
  <article class="banner" style="background-image: url(img/bg-3.jpg);">
    <section class="banner-copy">
      <h1>Stormy horizons</h1>
      <h5>and rainy nights</h5>
    </section>
  </article>
  <article class="banner" style="background-image: url(img/bg-4.jpg);">
    <section class="banner-copy">
      <h1>Beautiful sunrises</h1>
      <h5>and special breakfasts</h5>
    </section>
   </article>
</div>
The final code
html, body {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
}
.banners-container {
  display: table;
  width: 100%;
  height: 100%;
  table-layout: fixed;
  background-color: #000;
}
.banners-container:hover .banner {
  opacity: 0.3; 
}
.banners-container .banner {
  display: table-cell;
  height: 100%;
  width: 25%;
  background-size: cover;
  position: relative;
  background-position: center center;
  -webkit-transition: all 300ms ease;
  -moz-transition: all 300ms ease;
  -ms-transition: all 300ms ease;
  -o-transition: all 300ms ease;
  transition: all 300ms ease; 
}
.banners-container .banner:hover {
  width: 50%;
  opacity: 1; 
}
.banners-container .banner .banner-copy {
  position: absolute;
  bottom: 80px;
  width: 100%;
  text-align: center;
  color: #FFF; 
}

I hope that you enjoyed this tutorial and that you’ve learnt something new. Check back once in a while for more cool tutorials.

Posted in Development

Featured categories

SEO

UX

Your Partner In Digital

We are a small digital consultancy with a strong implementation team across digital marketing, technology and design.

Read More

Featured authors

Ecommerce Email Marketing & SMS Platform

Diginauts recommends Omnisend for your email and SMS automation needs for both Shopify and Woocommerce.

Get Omnisend

Related content

An experiment in data, headless CMS and NextJs

An experiment in data, headless CMS and NextJs

Diving into the vibrant world of aquariums, "Book of Neptune" is a fun side project that brings a fresh twist to fish keeping, blending tech savvy with the traditional joys of aquarium care. Far from just another app, it's a playful companion for hobbyists, aiming to...

Divi for WordPress

Diginauts recommends Divi, the premium page builder by Elegant Themes.

Get Divi