Creating a website Hero module with flexbox and the ‘vh’ unit

The hero module is widely used for websites. It usely consists of a large background image and a title. For this example I’ve also added a header with logo and menu button and two buttons for some call to action.

With Flexbox and the vh unit you can create a flexible hero module with efficient coding.

Browser support for Flexbox and the vh unit is great. You can read about browser support (and fallbacks) at the end of this article.

Step 1. The HTML structure

Let’s first start with the HTML. If this is overwhelming, don’t fear, I’ll go through it step by step.

<section class="hero">
<header id="header">
<a id="logo" href="#">logo</a>
<nav><a id="menu-icon">&#8801;</a></nav>
</header>
<header class="hero-header">
<h1 class="hero-title">The Title of this Hero Module</h1>
</header>
<footer class="hero-footer">
<a class="button button-primary" href="#">button one</a>
<a class="button" href="#">button two</a>
</footer>
</section>

For simplification I use text for the logo. This examples works well when using an image instead.

The HTML structure consists of three parts:

  1. #header with logo and menu icon
  2. hero-header with the title
  3. hero-footer with the buttons

The hero module itself is wrapped in a <section> with class .hero.

Step 2. The background image

The hero background image spans the full width and height of the browser viewport. You can achieve this by using the vh unit and the background property:

.hero {
height: 100vh;
background-image: url(https://images.unsplash.com/photo-1500417148159-68083bd7333a);
background-position: center;
background-size: cover;
background-repeat: no-repeat;
}

height is set to 100vh. This means the hero is using the full height of the viewport. vh is an abbreviation of viewport height. Setting it to 100 means: use 100% of the viewport height.

To make sure the background image spans the full width of the viewport, we use the property background-size with value cover. To align the image to the center of the viewport, you can usebackground-position: center;.

Step 3. Adding a header for the logo and menu icon

The hero is often used at the top of a page (e.g. Front Page). That’s why I’ve included a header with logo and menu symbol. With Flexbox you can easily align these items.

The HTML is pretty straight forward:

<header id="header">
<a id="logo" href="#">logo</a>
<nav><a id="menu-icon">&#8801;</a></nav>
</header>

I’ve used the unicode character&#8801; for the menu icon.

I want the logo at the left and the menu symbol at the right. Also, I want to vertically align both items.

In the old days we had to use something like floats (yikes!). But now we have the power of Flexbox. We only need three lines of code*:

#header {
display: flex;
justify-content: space-between;
align-items: center;
}

*) Actually, it’s more because you want to use prefixed code for Flexbox. See the section about Browser Support at the end of this article.

To use Flexbox for #header, we use display: flex;. With justify-content: space-between; you align the logo to the left and menu symbol to the right. The items are vertically aligned with align-items: center;.

That’s it (yeah!).

Step 4. Align the Hero Title and Buttons

What I wanted to achieve with this hero module:

  • header at the top
  • title at the middle
  • buttons at the bottom

Without Flexbox this is complicated. You could go with absolute positioning or some other CSS hacks. But guess what, with Flexbox it’s easy peasy :).

The condensed version of the HTML structure.

<section class="hero">
<header id="header">...</header>
<header class="hero-header">...</header>
<footer class="hero-footer">...</footer>
</section>

The CSS:

.hero {
display: flex;
flex-direction: column;
justify-content: space-between;
}

And again, only three lines of code. Sweat, isn’t it?

By default, flexbox items are aligned on a row. With flex-direction: column; we can change the direction to column. To distribute the items at the top, middle and bottom, we use justify-content: space-between;. This also ensures that they have equal space between. See the image below for some visual explanation.

With justify-content: space-between; you can easily distribute the items along the column.

Step 5. The Buttons

For the buttons, I want them on a single row. By default, you have a little space between them (because of display: inline-block). With Flexbox we can connect them seamlessly. Just a little detail I love!

The HTML:

<footer class="hero-footer">
<a class="button button-primary" href="#">button one</a>
<a class="button" href="#">button two</a>
</footer>

The CSS:

.hero-footer {
display: flex;
}

When using display: flex; all white space between it’s items (children) is deleted.

By default, the buttons have space between them (top). When using Flexbox, the buttons connects seamlessly (bottom).

Step 6. Using the ‘vh’ unit for text

The last step is applying the vh unit for all text. The benefit for this is that the text scales with the size of the viewport. It’s an easy way to have a flexible and consistent layout.

The text we are using in the hero module:

  • logo and menu symbol
  • hero title and buttons

The CSS for using the ‘vh’ unit:

#logo { font-size: 5vh; }
#menu-icon { font-size: 6vh; }
.hero-title { font-size: 9vh; }
.button { font-size: 3vh; }

5vh means the text size of the logo (#logo) is 5% of the viewport height. No matter the actual viewport height, the text size remains 5%.

Examples:

  • with a viewport height of 680px, the text size #logo is 5% of 680px = 34px
  • with a viewport height of 1440px, the text size is 72px

With just one line of code, the text size scales automatically with the viewport height. The fallback for the vh unit is pretty good, as you can read down below.

Codepen

I’ve created a pen for this example. So you can check out this example for yourself.

Hero module with Flexbox and the ‘vh’ unit, a pen on Codepen.

Hero module with Flexbox and the ‘vh’ unit, a pen on Codepen.

Browser Support for Flexbox

Browser support for Flexbox is great, but you need to prefix your CSS. With prefixed properties you have a global browser support of almost 98%.

Browser support for Flexbox on caniuse.com (Dec. 7, 2017)

Check browser support for Flexbox on caniuse.com.

Fallback for Flexbox

The most used fallback for Flexbox is using floats. You can use a CSS feature detector like Modernizr to use fallback styling. This article isn’t the place to go into full detail on this subject. There are a lot of resources online you can find about this.

Browser Support for the ‘vh’ unit

Browser support for thevh unit is okay. It is not supported by Internet Explorer 8, older Safari versions and Opera Mini. But fallback styling is easy to implement.

Browser support for the ‘vh’ unit on caniuse.com (Dec. 7, 2017)

Check browser support for the ‘vh’ unit on caniuse.com.

Fallback for the ‘vh’ unit

Browsers that don’t support the vh unit simply ignores these. Use a traditional font size values and follow it up with the vh value. Browsers that don’t support the vh unit simply ignore it.

Example for the vh unit fallback:

.hero-title { 
font-size: 3em; // fallback for 'vh' unit, you can also use px, %
font-size: 9vh;
}

Conclusion

Flexbox and the vh unit are rather new techniques you can use for laying out your website. They make your layout more flexible and uses less code.

Thanks for reading!

If you have something to say, please leave a comment or reach out to me on Twitter.