Search code examples
htmlcssimagelighthouse

Apply CSS style only to the loaded image from`<picture>` element


Lighthouse suggests using next-gen image formats for faster download and less data consumption. And this is done using HTML <picture> element.

So when we use <picture> element, how to target CSS style only to the loaded image?

In the snippet below, you can see that the border gets added to other elements as well.

picture * {
  border: 2px solid red;
}
<div style=" display: flex; gap: 30px; ">
  <p>AVIF: 50</p>
  <p>WebP: 100</p>
  <p>img: 150</p>
</div>

<picture>
  <source type="image/avif" srcSet="https://via.placeholder.com/50" width="50" height="50" />
  <source type="image/webp" srcSet="https://via.placeholder.com/100" width="100" height="100" />
  <img src="https://via.placeholder.com/150">
</picture>

Note: at the time of this writing, Chrome supports AVIF, Edge & Firefox support WebP, so the respective file type gets loaded based on your browser.

Screenshot of above snippet result taken from Microsoft Edge for reference:

HTML picture element styling


Solution

  • The loaded image will be represented by the img Tag so you can just target that element.

    The different source elements just provide different sources (therefore its called that way) but the browser decided what to use (by different factors) and load it into the img tag.

    You can either target it by the tag name (picture img) or add an actual css class (which i would recommend like picture .image - see snippet).

    picture .image {
      border: 2px solid red;
    }
    <div style=" display: flex; gap: 30px; ">
      <p>AVIF: 50</p>
      <p>WebP: 100</p>
      <p>img: 150</p>
    </div>
    
    <picture>
      <source type="image/avif" srcSet="https://via.placeholder.com/50" width="50" height="50" />
      <source type="image/webp" srcSet="https://via.placeholder.com/100" width="100" height="100" />
      <img class="image" src="https://via.placeholder.com/150">
    </picture>