Creating a Hero Image with CSS Grid

“Make Your Header Images Sooo Much Better”

It’s 2021.

I took a deep dive into CSS grid during UK Lockdown (exciting times).

CSS grid has been adopted by all the major browsers.

Let’s use CSS grid to create some hero images that are easy to understood, customize, and are fully responsive to look great on all devices.

I’m inspirational!

Hire me

<div class="hero-image">
  <div class="hero-tint">
    <div class="hero-content">
      <div class="hero-text">I'm inspirational!</div>
      <a class="hero-button" href="#contact-details" target="_blank">Hire me</a>
    </div>
  </div>
</div>

The hero-image is the overall container that will take the css background image. The hero-tint will stretch over the container and create a dark semi-transparent background, making the white text more readable. The hero-content is the container for the text and button. We will use CSS grid to position it on top of the .hero-tint div. A bit of text, a button/link. The standard stuff. Now let’s move onto where the grid magic will happens, the CSS.

But just before we get into the layout, I just want to highlight a little technique I use a lot when creating responsive layouts, the calc() function:

.hero-image {
  height: calc(300px + 20vw);
}

The first value inside the calc brackets is used to set the height when viewed in smaller windows, whilst the second value will create more height in larger windows as a percentage of the view/window width. I’ll be using it on quite a few elements to make the hero image and its contents scale responsively over all window sizes. Basically just have a play with it for now and remember the first value is for more pixels at small windows, the second for more pixels at larger windows.

OK onwards. First let’s source the background image, center it, make it cover the whole container. Then give the section a height (the width is automatically full width if left default):

.hero-image {
	background-image: url(assets/images/inspirational.jpg);
	background-position: center;
	background-size: cover;
	height: calc(300px + 20vw);
}

The calc function helps the hero-image div scale proportionately as the window increases.

Now lets cover the container with a semi-transparent div, give it a width and height of 100%. We’ll then make it a grid container and center the children of this container on both the x (justify) and y (align) axis with justify/align-items:

.hero-tint {
	width: 100%;
	height: 100%;
	background-color: rgba(0,0,0,0.3);
	display: grid;
	justify-items: center;
	align-items: center;
}

We’re about 90% done – we’ve got our hero image and a content section centered in the image.

Just a bit of tidying up to make it perfect.

Let’s use margins to position the content just off center both x and y. We will also make this hero-content a grid container so we can use the same justify-items property to center its children as well:

.hero-content {
	margin-left: calc(40px + 4vw);
	margin-bottom: calc(40px + 3vw);
	/* make this a grid container as well */
	display: grid;
	justify-items: center;
	grid-gap: calc(22px + 1vw);
}

You can leave off align-items this time, as by default CSS grid containers align their children to the start/top of the grid container, which works fine in this instance. A dash of grid-gap to create space between the text and the button.

Now it’s just a bit of text color and a responsive font size (again with my calc favourite):

.hero-text {
	color: white;
	font-size: calc(21px + 1vw);
}

Finally we style the button and its hover state:

.hero-button {
	border-radius: 5px;
	padding:
	calc(10px + 0.15vw)
	calc(15px + 0.15vw);
	background: rgba(0, 100, 200, 0.8);
	color: white;
	font-size: calc(8px + 1vw);
	text-decoration: none;
}
.hero-button:hover {
	background: rgba(200, 10, 10, 0.3);
	color: white;
}

That’s it, done. If you resize your window, you will see the hero image scales beautifully to look good at all view widths. And all with no media queries to muck about with : )

But hey, it’s Spiderman!

I’m a cleaner

Hire me

This one is similar but uses a 12 x 12 grid:

.hero-tint {
	grid-template-columns: repeat(12, 1fr);
	grid-template-rows: repeat(12, 1fr);
}

Then you can assign the content container to a point on this grid, and fine tune it’s placement with a bit of padding to push the grid around slightly.

.hero-two .hero-content {
	grid-column: 9 / 13;
	grid-row: 8 / 13;
	padding: 20px 0 0 10px; /* fine-tuning grid placement */
}

Turning the hero-text div into a grid container gets a bit messy with this one, so I just add space with a bit of margin below the hero-text:

.hero-text {
	margin-bottom: 30px;
}

So there you have it – two fully responsive hero images using CSS grid. Personally I use the first “inspirational” example – I find it simpler to understand and it works perfectly. The justify and align-items can take start/center/end, and with a bit of margin on the grid child you can position to your perfectionist heart’s desire. I keep this first hero image layout in a snippets folder (I use vim btw) and paste it in whenever I need it.

Anyway have a play with both of them and see which one suits you best:

Let me know how you get on in the comments. If you have any other ways of doing this I’d love to hear about them. Happy to answer any questions you may have.

happy Gridding

Mike

Leave a Reply

Your email address will not be published. Required fields are marked *