Exploring Art Direction to Dynamically Load Images
Tags: gatsby, graphql, css, design
Published: 2020-07-05 20:03:43

---
title: Exploring Art Direction to Dynamically Load Images
published: true
description: The header image on my site now dynamically changes based on the screen size. Read how I implemented this without the browser needing to preload twice as many images: 
tags: Gatsby, GraphQL, CSS, Design
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/fq9lmocgvaultj88mjif.gif
canonical_url: https://www.aboutmonica.com/blog/2020-06-24-exploring-art-direction-in-gatsby
---

While updating [my homepage](https://www.aboutmonica.com/) to include my newly-commission illustration from [Aishwarya Tandon](https://toondoon1010.carbonmade.com/), I wanted to load different versions of the image based on screen-size in a performant way. For my header image, I use [gatsby-image](https://www.gatsbyjs.org/packages/gatsby-image), an official GatsbyJS plugin that optimizes images that makes it straightforward to control how images are progressively enhanced on page load. One of my favorite built-in Gatsby image effects is <a href="https://using-gatsby-image.gatsbyjs.org/traced-svg/">traced SVGs</a>, which renders an SVG tracing of an image, in a pre-determined color before the image fully loads. You can explore all of gatsby-image's built-in loading effects on the [using-gatsby-image](https://using-gatsby-image.gatsbyjs.org/) site.

![](https://dev-to-uploads.s3.amazonaws.com/i/hgh3424t181r19opkiu7.gif)
_The above GIF illustrates how gatsby-image transitions from traced SVG to the loaded image_

While looking into how to load different images at different breakpoints without unnecessarily downloading files I discovered gatsby-image's built-in support for this feature which is known as [art direction](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images#Art_direction). Modern HTML can be used to dynamically load of images based on screen size using `srcset` attributes with `<img>` and `<source>` instead of JavaScript. Swapping images at different screen sizes can be done with JavaScript or CSS instead of native HTML attributes however using the HTML attributes can improve page loading performance as it prevents unnecessarily preloading two images when only one image from the `srcset` needs to be visible within the viewport on load.

![](https://dev-to-uploads.s3.amazonaws.com/i/fq9lmocgvaultj88mjif.gif)
_The above GIF shows the transition between different images loaded with art direction within gatsby-image_

All images that use the gatsby-image plugin need to be constructed using a GraphQL query. Below is a slightly modified version of the `useStaticQuery()` I used to load image files into gatsby-image's `Img`. Within `useStaticQuery()` I wrote two named queries `mobileImage` and `desktopImage` to load both versions of the image I wanted on mobile as well as the desktop.

```jsx
import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Img from "gatsby-image"

const Avatar = () => {
  const data = useStaticQuery(graphql`
    query {
      mobileImage: file(
        relativePath: { eq: "animonica-headshot-cropped.png" }
      ) {
        childImageSharp {
          fluid(maxWidth: 300, quality: 100) {
            ...GatsbyImageSharpFluid_tracedSVG
          }
        }
      }
      desktopImage: file(relativePath: { eq: "animonica-full.png" }) {
        childImageSharp {
          fluid(maxWidth: 300, quality: 100) {
            ...GatsbyImageSharpFluid_tracedSVG
          }
        }
      }
    }
  `)

  const sources = [
    data.mobileImage.childImageSharp.fluid,
    {
      ...data.desktopImage.childImageSharp.fluid,
      media: `(min-width: 625px)`,
    },
  ]

  return <Img fluid={sources} alt="Illustrated Monica" />
}

export default Avatar
```

If you inspect my site's header using Dev Tools you'll notice there's two `<picture>` sections, one that includes the tracedSVGs that are generated by `GatsbyImageSharpFluid_tracedSVG` in the image query and another with the `.png` files.

The HTML that ultimately renders to load the .png files from the earlier use of gatsby-image resembles the below:

```html
<picture>
  <source media="(min-width: 625px)" srcset="animonica-full.png" />
  <source srcset="animonica-headshot-cropped.png" />
  <img src="animonica-full.png" alt="Illustrated Monica" />
</picture>
```

The media attribute in the `<source>` elements, within `<picture>`, determines which image `srcset` is displayed. The first condition that is met will be displayed, in the case where neither media condition is true _or_ the browser doesn't support the `<picture>` element it will return the `<img>` element from within the `<picture>`. You can view current browser compatability for `<picture>` at [Can I use this?](https://caniuse.com/#feat=picture).

As a recap, within `gatsby-image` we can pass an array of images to generate HTML's art direction related attributes. Using this approach instead of CSS or JavaScript reduces the number of assets that need to be preloaded in the browser. My current Gatsby site, displays a complete HTML page from the server to the client on the initial load without requiring JavaScript therefore I've found it helpful to avoid delegating certain tasks to JavaScript that HTML/CSS can handle in a more performant way. I've written more about this topic in my article [Less JavaScript Makes Font Awesome More Awesome](https://www.aboutmonica.com/blog/less-javascript-is-more).


The article was originally published at [aboutmonica.com](https://www.aboutmonica.com)