</>Jonathan Harrell

Main Menu

Site Tools

Semantic Image Overlays With Object-Fit

Think of how many times you have coded a grid of images with an overlay that appears on hover and displays some sort of text. With the object-fit property getting wider support, there is now a clean, semantic way of doing this.

The Old Way (without object-fit)

Link to this section

Here’s how I used to accomplish this:

<article class="blog-post-teaser">
  <div
    class="image"
    style="background-image: url(...)"
  ></div>
  <div class="overlay">
    <h2>
      <a href="...">
        Article Title
      </a>
    </h2>
  </div>
</article>

The markup involved an article containing a plain div with a background image applied, and an overlay div that contained the text that needed to sit on top of the image. I would then absolutely position both the image and the overlay. The size of the div would be determined by a little percentage padding trick on the article:

.blog-post-teaser {
  position: relative;
  padding: 30% 0;
}

.blog-post-teaser .image {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.blog-post-teaser .overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

This approach gives us a lot of control but it’s really not as semantic as it could be. The image for each article seems like a pretty important piece of content, and the browser doesn’t know that it’s an image. And we can’t feed in alt tags to help with SEO.

How do we improve semantics while retaining control of the image sizing so everything fits nicely into a grid? Enter object-fit.

The New Way (with object-fit)

Link to this section

Here’s what my markup looks like now:

<article class="blog-post-teaser">
  <figure>
    <img src="..." alt="...">
    <figcaption>
      <h2>
        <a href="...">
          Article Title
        </a>
      </h2>
    </figcaption>
  </figure>
</article>

Now the browser knows we’re serving up an image. It even knows that the article title is both a heading for the article and a caption for the image. Search engines can now access alt text. Let’s look at the styling:

.blog-post-teaser figure {
  position: relative;
  padding: 30% 0;
}

.blog-post-teaser figcaption {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

.blog-post-teaser img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

It’s almost identical, only that now we’re using the figure element to control sizing, and we’re using the object-fit property on the image element. This works the exact same way as setting background-size: cover. The image will fill the specified space without stretching.

Browser Support of object-fit

Link to this section

Currently object-fit is not supported in IE or Edge, but there is a simple polyfill you can use to convert the image to a background-image in those browsers.

Check out the live demo to see the styles in action, as well as some additional gradient and hover effects to make it more snazzy.

Go to experiment

Semantic Image Grid with Object-Fit

Click here to view the experiment on Codepen

More Articles

Go to article

System-Based Theming with Styled Components

Learn how to support system-based theming in Styled Components, while allowing a user to select their preferred theme and persist that choice.

Go to article

Implicit State Sharing in React & Vue

Learn to use React’s Context API and provide/inject in Vue to share state between related components without resorting to a global data store.

Go to article

Component Reusability in React & Vue

Learn how to use render props in React and scoped slots in Vue to create components that are flexible and reusable.

Go to article

What’s the Deal with Margin Collapse?

Learn about margin collapse, a fundamental concept of CSS layout. See visual examples of when margin collapse happens, and when it doesn’t.