Gatsby: Can't get consistent Gatsby Img behavior

Created on 18 Jul 2018  ยท  10Comments  ยท  Source: gatsbyjs/gatsby

Description

I've finally managed to get Gatsby images work as expected on desktop devices, to find out that they are totally not working on mobile safari/firefox/chrome on ios devices. Moreover, I can't get consistent behavior of images when deploying my project on gh-pages. One deploy everything works, other one, with no changes at all, images just get stuck on blur phase. I found a temporary fix of deleting cache folder in my project, but I don't think that it's the best way of solving this.

Steps to reproduce

Plugins that I use
`` { resolve:gatsby-source-filesystem, options: { path:${__dirname}/src/posts, name: 'posts', }, }, { resolve:gatsby-source-filesystem, options: { name:images, path:${__dirname}/src/assets/images, }, }, { resolve:gatsby-source-filesystem, options: { name:photos, path:${__dirname}/src/assets/photos, }, }, { resolve:gatsby-source-filesystem, options: { name:headers, path:${__dirname}/src/assets/headers`,
},
},

{
  resolve: `gatsby-transformer-remark`,
  options: {
    plugins: [
      {
        resolve: `gatsby-remark-images`,
        options: {
          maxWidth: 630,
        },
      },
      'gatsby-remark-copy-linked-files',
    ],
  },
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
`gatsby-plugin-react-helmet`,
`gatsby-plugin-sass`,

],

Queries (note: they are placed in separate pages):

export const query = graphql query HeaderQuery { headerImage: imageSharp(id: { regex: "/headers/" }) { sizes(maxWidth: 2000) { ...GatsbyImageSharpSizes_tracedSVG } } }
export const query = graphql query PhotosQuery { allFile( filter: { extension: { regex: "/(jpeg|jpg|gif|png)/" } sourceInstanceName: { eq: "photos" } } ) { edges { node { childImageSharp { sizes(maxWidth: 2000) { ...GatsbyImageSharpSizes } } } } } }

Images:

{data.allFile.edges.map(entry => ( test ))}

className="header-legal"
title="Header image"
alt="test"
sizes={data.headerImage.sizes}
/>
`



### Expected result

1)I expect everything to work on every `npm run develop` or `npm run deploy` but from time to time they are not working in both development mode and build mode.
2)I expect images to have lazy load on mobile devices, but it seems like they don't even have blur, when page loads and behave like normal `<img>`

### Actual result
You can see demo of not working mobile images here:

https://d-ivashchuk.github.io/taurus-gatsby/photos

Or here:

https://d-ivashchuk.github.io/taurus-gatsby/legal

### Environment


System:
OS: macOS Sierra 10.12.6
CPU: x64 Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz
Shell: 3.2.57 - /bin/bash
Binaries:
Node: 6.10.1 - /usr/local/bin/node
npm: 6.1.0 - /usr/local/bin/npm
Browsers:
Chrome: 67.0.3396.99
Firefox: 56.0.2
Safari: 11.1.2
npmPackages:
gatsby: ^1.9.243 => 1.9.273
gatsby-image: ^1.0.54 => 1.0.54
gatsby-link: ^1.6.40 => 1.6.45
gatsby-plugin-google-analytics: ^1.0.24 => 1.0.31
gatsby-plugin-react-helmet: ^1.0.8 => 1.0.8
gatsby-plugin-sass: ^1.0.25 => 1.0.26
gatsby-plugin-sharp: ^1.6.48 => 1.6.48
gatsby-remark-copy-linked-files: ^1.5.30 => 1.5.37
gatsby-remark-images: ^1.5.60 => 1.5.67
gatsby-source-filesystem: ^1.5.27 => 1.5.39
gatsby-transformer-remark: ^1.7.39 => 1.7.44
gatsby-transformer-sharp: ^1.6.27 => 1.6.27
npmGlobalPackages:
gatsby-cli: 1.1.58
```
Apart from this issue I want to thank you guys for creating Gatsby and helping people like me to become proficient with it. Great Job!

question or discussion

All 10 comments

I am trying to reproduce it, but everyting works fine on iphone(images get blurred and appear as expected).
I've tried to isolate everything, created new project using gatsby-starter-photon and created one page solely with an image there. One query, one image, same behavior as in my project where I get a mistake, image loads as if it is normal one, no blur at all on iphone, but everything works fine on desktop.
It is nothing special really, I've just follwed tutorial but for some reason it does not work on mobile devices.
I thought maybe it can conflict with gatsby-starter-photon in terms of styles or js and produce such behavior?

This is the closest I could get to reproducing this issue in more or less isolated environment.

https://d-ivashchuk.github.io/test/

I've used gatsby-starter-default and added gatsby-image to it. When deployed to gh-pages, lazy-loading works on desktop devices, but fails to work on mobile ios(at least, can't test on android at the moment)

Thanks for patience and help!

Ah yeah โ€” lazy loading doesn't work on IOS due to it not supporting IntersectionObserver. Closing this in favor of https://github.com/gatsbyjs/gatsby/issues/4021 as we need to document this.

@KyleAMathews currently the newest version of iOS Safari supports IntersectionObserver. However, I am still getting weird behaviour and on Safari is loading extremely huge images on mobile.

I believe is due to Safari not support WebP. As per @coreyward comments here: https://github.com/gatsbyjs/gatsby/issues/4926 Could it be? What should be the workaround?

@PolGuixe Are you using source images that are in WebP or setting the format argument to webp?

The srcSet field returned by Gatsby Image will include only the original format of the image unless you specify the format argument. If you use a fragment that specifies _withWebp, like GatsbyImageSharpFixed_withWebp, it will include the srcSetWebp field which will be included in the srcset attribute that is rendered as part of the Gatsby Image component, but with the original srcSet data as a fallback.

Which is all to say that you can safely include WebP images in a srcset served to Safari provided you do not _only_ have WebP images in that srcset, and with Gatsby Image, the only way to mess that up is to either have your original images in WebP (exceedingly unlikely) or to set the format argument to webp.

If neither of these are the case and you are using a recent version of Gatsby Image (e.g. 2.2.x+) you may want to open a new, fully detailed issue.

@coreyward

Gatsby-Image: v2.2.4

// usage example
// ...
<Image
  {...query.prismicRestaurant?.data?.body_image?.localFile
   ?.childImageSharp}
  className={classes.image}
/>
//...

// query example
// ...
  body_image {
          localFile {
            id
            childImageSharp {
              fluid(maxWidth: 1200, quality: 100) {
                ...GatsbyImageSharpFluid_withWebp
              }
            }
          }
        }
//...

HTML code generated
Screenshot 2019-07-11 at 18 04 40

I don't see the srcSetWebp

Network:
In this case I scrolled down as soon as page loaded.
Screenshot 2019-07-11 at 18 03 00

In this case I waited for the first images to load and then scrolled and the other images started downloading afterwards,
Screenshot 2019-07-11 at 18 09 38
but many of them...

Should I open different bugs?

Since you're using fluid with a maxWidth: 1200, the sizes attribute tells the browser that the image will be shown at 100vw on viewports narrower than 1200px. Since your mobile device is likely rendering at a higher DPI, the browser will select an image that suits accordingly. For example, on a 375px wide display with a device pixel ratio of 2, the browser would expect to render the image at 750px wide. The closest match that won't result in a lower quality display is the 1200px wide image, so that's what would most likely be selected by the browser.

That 1200px wide image would probably be a smaller file size, but you've set the quality to 100%, which will result in minimal compression and large file sizes.

As for additional images loading, you have caching disabled, which is not an expected condition for normal users; if you re-enable caching you'll likely see that those images are not re-requested from the server but instead served from cache.

srcSetWebp is a field that the GatsbyImageSharpFluid_withWebp Gatsby Image fragment specifies. You don't need to know about it as a user, just providing details so you're aware of what's going on

@coreyward I am using quality 100% to accentuate the effect of these big pictures. ๐Ÿ˜… Won't go like this into production.

I've checked the size of the image downloaded and instead of 1200px, the image is 1800px which is the next resolution step. The device I am using for testing is an iPhone 8 Plus. _Edit:_ pixel ratio on this device is about 3, screen width 414px --> 414*3= 1242 > 1200 hence it jumps to the next resolution step.

Just to confirm best practices:

  1. Is it fine to use Webp format fragments even if the site is targeted to Safari because a fallback is generated and this will be used.

  2. In a fluid fragment, the maxWidth should be the maximum container width in the biggest screen size that needs to be supported.

  3. Quality set to 100% is not recommended to get fast-loading sites... ๐Ÿ˜…

I'll keep doing a test to see if I can get a good consistency.

Is it fine to use Webp format fragments even if the site is targeted to Safari because a fallback is generated and this will be used.

If you know that this is exclusively going to be used by iOS you could just leave off the _withWebp part of the fragment, but if you leave it there there's no real harm (a few extra bytes of data in the srcset).

In a fluid fragment, the maxWidth should be the maximum container width in the biggest screen size that needs to be supported.

If by this you mean that the maxWidth should be the largest that this image is displayed (i.e., its maximum contained size), then yes. If you're doing something where it's only displayed at, say, 50% of the viewport width (50vw) you can actually override the sizes attribute to provide a more accurate recipe for the browser, but the default is fairly safe.

Quality set to 100% is not recommended to get fast-loading sites... ๐Ÿ˜…

๐Ÿ˜‰

Was this page helpful?
0 / 5 - 0 ratings

Related issues

signalwerk picture signalwerk  ยท  3Comments

Oppenheimer1 picture Oppenheimer1  ยท  3Comments

kalinchernev picture kalinchernev  ยท  3Comments

jimfilippou picture jimfilippou  ยท  3Comments

ghost picture ghost  ยท  3Comments