diff --git a/packages/gatsby-remark-images/.babelrc b/packages/gatsby-remark-images/.babelrc index 9f5de61e0d79e..c5aaeee07bfaf 100644 --- a/packages/gatsby-remark-images/.babelrc +++ b/packages/gatsby-remark-images/.babelrc @@ -1,5 +1,5 @@ { "presets": [ - ["babel-preset-gatsby-package"] + ["babel-preset-gatsby-package", { "browser": true }] ] } diff --git a/packages/gatsby-remark-images/.gitignore b/packages/gatsby-remark-images/.gitignore index f566442b32d84..dcc20e9f74bf9 100644 --- a/packages/gatsby-remark-images/.gitignore +++ b/packages/gatsby-remark-images/.gitignore @@ -1,3 +1,5 @@ +/constants.js +/gatsby-browser.js /index.js /__tests__/* tests \ No newline at end of file diff --git a/packages/gatsby-remark-images/src/__tests__/__snapshots__/index.js.snap b/packages/gatsby-remark-images/src/__tests__/__snapshots__/index.js.snap index ea1d0153fdfef..8408dd6ad2456 100644 --- a/packages/gatsby-remark-images/src/__tests__/__snapshots__/index.js.snap +++ b/packages/gatsby-remark-images/src/__tests__/__snapshots__/index.js.snap @@ -1,119 +1,97 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`it handles goofy nesting properly 1`] = ` -" - - + \\"test\\" - - - " + " `; exports[`it leaves images that are already linked alone 1`] = ` -" - - + \\"img\\" - - - " + " `; exports[`it leaves linked HTML img tags alone 1`] = ` " - - - \\"this - + + \\"this - " `; exports[`it leaves single-line linked HTML img tags alone 1`] = ` -" - - - \\"this - - - " +" + + \\"this + " `; exports[`it transforms HTML img tags 1`] = ` -" - - - - - \\"my - +" + + + \\"my - - - " + " `; exports[`it transforms images in markdown 1`] = ` -" - - - - + \\"image\\" - - - - " + " `; diff --git a/packages/gatsby-remark-images/src/constants.js b/packages/gatsby-remark-images/src/constants.js new file mode 100644 index 0000000000000..69e5d9b58c01d --- /dev/null +++ b/packages/gatsby-remark-images/src/constants.js @@ -0,0 +1,3 @@ +exports.imageClass = `gatsby-resp-image-image` +exports.imageWrapperClass = `gatsby-resp-image-wrapper` +exports.imageBackgroundClass = `gatsby-resp-image-background-image` diff --git a/packages/gatsby-remark-images/src/gatsby-browser.js b/packages/gatsby-remark-images/src/gatsby-browser.js new file mode 100644 index 0000000000000..fb8fcbc95670b --- /dev/null +++ b/packages/gatsby-remark-images/src/gatsby-browser.js @@ -0,0 +1,35 @@ +const { + imageClass, + imageBackgroundClass, + imageWrapperClass, +} = require(`./constants`) + +exports.onRouteUpdate = () => { + const imageWrappers = document.querySelectorAll(`.${imageWrapperClass}`) + + // https://css-tricks.com/snippets/javascript/loop-queryselectorall-matches/ + // for cross-browser looping through NodeList without polyfills + for (let i = 0; i < imageWrappers.length; i++) { + const imageWrapper = imageWrappers[i] + + const backgroundElement = imageWrapper.querySelector( + `.${imageBackgroundClass}` + ) + const imageElement = imageWrapper.querySelector(`.${imageClass}`) + + const onImageLoad = () => { + backgroundElement.style.transition = `opacity 0.5s 0.5s` + backgroundElement.style.opacity = 0 + imageElement.style.transition = `opacity 0.5s` + imageElement.style.opacity = 1 + imageElement.removeEventListener(`load`, onImageLoad) + } + + if (imageElement.complete) { + backgroundElement.style.opacity = 0 + } else { + imageElement.style.opacity = 0 + imageElement.addEventListener(`load`, onImageLoad) + } + } +} diff --git a/packages/gatsby-remark-images/src/index.js b/packages/gatsby-remark-images/src/index.js index afb3aed2af772..795bccf80c569 100644 --- a/packages/gatsby-remark-images/src/index.js +++ b/packages/gatsby-remark-images/src/index.js @@ -1,4 +1,8 @@ -// const select = require(`unist-util-select`) +const { + imageClass, + imageBackgroundClass, + imageWrapperClass, +} = require(`./constants`) const visitWithParents = require(`unist-util-visit-parents`) const path = require(`path`) const isRelativeUrl = require(`is-relative-url`) @@ -90,9 +94,6 @@ module.exports = ( return resolve() } - // Calculate the paddingBottom % - const ratio = `${(1 / fluidResult.aspectRatio) * 100}%` - const originalImg = fluidResult.originalImg const fallbackSrc = fluidResult.src const srcSet = fluidResult.srcSet @@ -104,14 +105,18 @@ module.exports = ( const fileNameNoExt = fileName.replace(/\.[^/.]+$/, ``) const defaultAlt = fileNameNoExt.replace(/[^A-Z0-9]/gi, ` `) - // TODO - // Fade in images on load. - // https://www.perpetual-beta.org/weblog/silky-smooth-image-loading.html - - const imageClass = `gatsby-resp-image-image` - const imageStyle = `width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px ${ - options.backgroundColor - };` + const imageStyle = ` + width: 100%; + height: 100%; + margin: 0; + vertical-align: middle; + position: absolute; + top: 0; + left: 0; + box-shadow: inset 0px 0px 0px 400px ${options.backgroundColor};`.replace( + /\s*(\S+:)\s*/g, + `$1` + ) // Create our base image tag let imageTag = ` @@ -124,7 +129,7 @@ module.exports = ( srcset="${srcSet}" sizes="${fluidResult.sizes}" /> - ` + `.trim() // if options.withWebp is enabled, generate a webp version and change the image tag to a picture tag if (options.withWebp) { @@ -162,29 +167,31 @@ module.exports = ( src="${fallbackSrc}" alt="${node.alt ? node.alt : defaultAlt}" title="${node.title ? node.title : ``}" - src="${fallbackSrc}" /> - ` + `.trim() } + const ratio = `${(1 / fluidResult.aspectRatio) * 100}%` + // Construct new image node w/ aspect ratio placeholder const showCaptions = options.showCaptions && node.title let rawHTML = ` ${imageTag} + > + ${imageTag} - ` + `.trim() // Make linking to original image optional. if (!inLink && options.linkImagesToOriginal) { @@ -196,19 +203,19 @@ module.exports = ( target="_blank" rel="noopener" > - ${rawHTML} + ${rawHTML} - ` + `.trim() } // Wrap in figure and use title as caption if (showCaptions) { rawHTML = `
- ${rawHTML} -
${node.title}
+ ${rawHTML} +
${node.title}
- ` + `.trim() } return rawHTML