How to overlay divs without absolute positioning it.

November 29, 2019

Written by Thomas Duffy

A common task while styling HTML is overlaying two divs. The job could be overlaying some text over an image, or popping a modal over the top of an overlay. In this post, we’ll cover how to accomplish overlaying two divs without having to use position:absolute.

Why not just make the div position:absolute?

First things first, I want to make it clear that using position:absolute is entirely acceptable to complete the task of overlaying two divs. This topic is commonly brought up because when positioning an element with position:absolute it removes the element from the natural flow of the document, which can make it challenging to manage. Still, it doesn’t mean its wrong by any means.

The cleaner way!

In the above paragraph, I stated that it’s not wrong to use position:absolute to overlay two divs, but something to also mention is, just because it’s not wrong doesn’t mean it won’t make you want to take a shower after using it. Ok, it’s not that bad, but there is a cleaner way! Lets look at how to get the job done with the fantastic new powerful CSS grid layout system.

Example

Below is an example when you would have to overlay two divs. The example is a hero banner with a title and a product image. The requirements are that It needs to be responsive and allow the title to overlay the image at smaller screen sizes.

The solution using Grid

Before Grid Layout came along, most people would set the right div to position: absolute, taking the div out of the document flow and requiring the left element to ignore the position of the right element. With Grid, you can assign the divs to live on the same columns and rows, resulting in the same effect while keeping both elements in the natural document flow. Let’s take a look at the code.

HTML

<div class="container">
  <div class="left-content">
    <h1>YJ conversion kit! Get your kit now!</h1>
    <div class="cta-button">More Info</div>
  </div>
  <div class="product-image"></div>
</div>

Above is the HTML for our hero banner. We have a container with two divs as children. The element with the class of .left-content is going to wrap our title and call to action button, the element with the class of .product-image is going to contain, well, you guessed it, our product image.

CSS

The first thing we need to do is give the container wrapping all the elements the property of display: grid, which will allow us to apply all the other necessary styles to its children to accomplish the overlaying effect. Next, we have to define the grid columns and rows. We can do this by using the grid-template-columns and grid-template-rows. In this example, we’ll use a 4 column layout with one row. To make this responsive, we can use the fr shorthand to declare that you want all your columns to take up the available space in the container. Then, we’ll define the grid rows. With this example, we only want one row.

.container {
  display: grid;
  grid-template-columns: 1fr 1 fr 1fr 1fr;
  grid-template-rows: 1fr;
  height: 300px;
}

columns and rows The above CSS will give us our columns and rows.

Next, let’s position our elements inside the container. First, we’ll target the .left-content class. Instead of giving the element a width, we need to define what rows and columns we want this element to span across. The way we can do this is by using grid-column-start, grid -column-end, grid-row-start, and grid-row-end.

.left-content {
  grid-column-start: 1;
  grid-column-end: 3;
  grid-row-start: 1;
  z-index: 2;
  padding-left: 16px;
}

Lets break down the above CSS. By setting grid-column-start to 1 and grid-column-end to 3 we are saying that we want this element to span across column 1 to the beginning of column 3. So basically 50% of the container. You maybe asking, why define grid-row-start if you only have 1 row? We have to define grid-row-start because the browser will dynamically create new rows and automatically place each element on that row. Defining both elements to grid-row-start: 1 will force the two elements to be on the same row.

columns and rows

Next, let’s position our product image.

.product-image {
  grid-column-start: 2;
  grid-column-end: 5;
  grid-row-start: 1;
  background-image: url('./src/example-image.png');
  background-position: right bottom;
  background-repeat: no-repeat;
  background-size: contain;
  z-index: 1;
}

So this is where the magic happens. By setting this element to grid-column-start to 2, we are assigning this div to one of the same columns as the first element, allowing the overlapping effect to take place without using absolute.

columns and rows

Conclusion

To recap, all we have to do is define what row and column to start and end. Then the div will automatically span across the defined grid columns and rows. Since we only have one row, we are not setting the grid-row-end , but we still have to define grid-row-end, or the browser will automatically create multiple rows dynamically. I hope you enjoyed this article on how to overlap two divs using the new Grid layout system!

Play with the code here!


Written by Thomas Duffy

Want to Build animations like the one above?

Sign up and get notified when I release my mini course on building animations with React.