Replace the Image in an <img> with CSS

Avatar of Marcel Shields
Marcel Shields on (Updated on )

The following is a guest post by Marcel Shields. Marcel was in a difficult place where he needed to change the image on a page but didn’t have access to the HTML. Rare, but I’m sure we’ve all be in weird situations like this. He explains how he managed to replace that image without needing to access the HTML or JavaScript. Also turns out to be a pretty good way to replace anything with an image.

I just wanted to share something I found really cool about using CSS box-sizing. Chris wrote a really good introduction a few years back if you’re not familiar with the property. It makes things a lot more sane when thinking about layout. People love it so much, they put it on everything like hot sauce. I wanted to share how I found it useful as (yet) another image replacement technique.

A few days ago at work, I was asked to replace an <img> on our site with another image hosted elsewhere. Simple right? But the catch was I would not be able to replace the markup as it was already deployed to production, but could inject CSS or JS through our CMS. For whichever technology I chose, it would be inserted on all site pages. I only needed on one specific page, and the attributes of parent containers were non-specific to the desired page.

  <title>Really Cool Page</title>
  <!-- .header would be across site on other pages with different children, so no background image adding -->
  <div class="header">
    <img class="banner" src="//">

This is simple to do with JavaScript, but I wanted to see if there was another, even simpler, way. After a few iterations in Chrome Dev Tools, I thought to use the box-sizing property to keep dimensions strict, add the new image as a background image, and just push the inline image out of the way with padding and see what happened.

/* All in one selector */
.banner {
  display: block;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
  background: url( no-repeat;
  width: 180px; /* Width of new image */
  height: 236px; /* Height of new image */
  padding-left: 180px; /* Equal to width of new image */

It worked beautifully. Here’s what’s cool:

  • It works on just about any element, even empty ones like <img> or <hr>
  • Browser support is excellent (Chrome, Firefox, Opera, Safari, IE8+)
  • Refrains from using SEO unfriendly display: none or other properties

That last point seemed important, as it works really well for text replacement too without any adjustment. Check it out!