Understand Responsive Images Through gatsby-image
By: Trang Le
Tags: Responsive Design, Programming, React, JavaScript, Gatsbyjs

The Anatomy of a Responsive Image

Here is the markup of both the fixed and fluid images generated by gatsby-image .

Markup of fixed and fluid images generated by gatsby-image.

Whether an image is fixed or fluid, it’s always wrapped inside a <div> element named gatsby-image-wrapper .

The first element inside the wrapper is a placeholder image.

We can tell that it’s a placeholder because its attribute is aria-hidden=”true” , and the image’s dimension is 20x13.

This placeholder serves two purposes when the browser hasn’t finished loading the actual image:

Gives a smooth transition with the “blur-up” technique popularized by none other than Medium.

Prevents image jump.

If you refresh the browser, you will see that familiar blur-up effect.

Blur-up effect.

To tell you the truth, the blur-up effect is best experienced when the internet is slow, and this may well be the only good thing about slow internet. It lets us developers enjoy the fruits of our labor and the marvel of technology.

Right underneath the placeholder image is an empty <div> that only appears when the image is set to fluid.

This element adds a bottom padding to the image. Its value is the same as the image’s aspect ratio: 2592/3888 = 0.6666.

This empty <div> is needed because both the gatsby-image-wrapper and the actual image have no predefined width and height. At the same time, the actual image has to take up the whole width and height of its parent.

Without the empty container with the bottom padding, the actual image will disappear.

Finally, the <picture> element.

There is nothing special about this tag, but it houses two important elements: <source> and <img> . Because they are so pivotal in the layout of the image, I’ll put them in dedicated headings.

<source> element

The most important attribute of the <source> element is srcset . It provides a bunch of images with hints to help the browser pick the right one for different viewport widths.

Notice that srcset differs between fixed and fluid images.

For the fixed image:

Fox the fluid image:

As you can see, each image in srcset is separated from the previous one by a comma. Each one contains:

The path to the image ( /static/362300c046749582c4ff6569a40211d8/25b50/james-mccullough-Znxkw16UKG0-unsplash.jpg ).

). A space.

The x descriptor in case of a fixed image and w descriptor for a fluid one.

x refers to pixel density. The x descriptor specifies the pixel density the image is intended for.

In this example, the default image is 35KB, but it expands to 68KB when the pixel density is 1.5 times the standard (107KB when double).

It’s a huge leap from 35 to 68, and then to 107. Thus you can see the importance of serving the right image for the right screen device.

Meanwhile, the w in the w descriptor refers to the image’s instrinsic width in pixels. Note that it is set in w unit — not px , as we often see. This is the image’s real size and you can verify that by inspecting the file on your computer.

The w descriptor is only applied to fluid images because, with fixed images, we have only one single image size that we want to display regardless of the situation.

In this demo, the w descriptor values are 1750w, 350w, 700w, 1050w, and 1444w and 3888w. Did you notice the pattern?

3888w happens to be the width of the original image.

At the same time, we have set the maxWidth of our fluid image to 300. That means gatsby-plugin-sharp generates automatic sizes that are 50%, 100%, 150%, and 200% of the value we set in the GraphQL query. That’s very thoughtful.

Also, in the case of a fluid image, we have another attribute in the <source> element: sizes .

This attribute defines a set of media conditions and the corresponding images to serve when the condition is true.

<picture> <source sizes="(max-width:700px) 100vw, 700px></source> </picture>

The hint above tells the browser to make the image span 100% of the viewport when the browser window is 700px wide and below. Otherwise, just serve an image that is 700px wide.

At the same time, this hint also satisfies our GraphQL query that specifies that the image never exceeds 700px in width.

The actual image

Finally, we get to the all-important <img> tag. Without it, the actual image won’t appear.

Its sizes and srcset attributes are the same as the ones in the <source> element.

The attribute of note here is src . Do you remember that the media condition tells the browser to load a 700px wide image when the viewport is above 700px?

This src attribute embeds that very image.

Actually, that’s all there is to the actual image. So much groundwork for one image.