Skip to content

Commit

Permalink
feat(gatsby-image): Add gatsby-image/withIEPolyfill export with objec…
Browse files Browse the repository at this point in the history
…t-fit/position support (#12681)

## Description

This PR will allow users who want `object-fit/object-position` support in IE to simply `import Img from "gatsby-image/withIEPolyfill"` instead of importing directly from `"gatsby-image"`.

Please feel free to review the PR and let me know if the implementation can be improved.

The `/withIEPolyfill` version of `gatsby-image` currently does the following:

1. Checks if the browser supports the `object-fit/position` CSS properties.
  a. If yes, no polyfill is loaded.
  b. If no, the `object-fit-images` polyfill is imported and called.
2. Wraps `gatsby-image` in a component that passes the new `objectFit` and `objectPosition` prop values to the polyfill implementation (which requires a weird `font-family` hack).

### New props

To make the implementation simple, I've added new `objectFit` and `objectPosition` props that will needed to be used to pass the corresponding values to the polyfill. This is to avoid a scenario where a user attempts to set these values in a way we can't pass to the polyfill (e.g. via an external CSS stylesheet) and doesn't understand why the polyfill isn't working. Let me know if this API can be improved.

### Loading polyfill in /withIEPolyfill/index.js

I opted to load the `object-fit-images` polyfill directly in `withIEPolyfill/index.js` rather than in `gatsby-browser.js`. If anyone knows of a better way to approach this, please let me know and feel free to make improvements.

### Polyfill repo has been archived

I was surprised to see that the `object-fit-images` [repo](https://github.com/bfred-it/object-fit-images) has recently been archived by its owner. It still works, but if anyone is concerned about this or knows of a reliable alternative polyfill, please let me know.

### Docs to be updated once implementation is finalized

Once we've settled on the API for this `/withIEPolyfills` component, a brief explanation will need to be added to the `gatsby-image` docs. I held off on adding one for now in case we end up changing the API.

## Related Issues

Fixes #4021.

Co-authored-by: Ward Peeters <[email protected]>
  • Loading branch information
ooloth and wardpeet committed Mar 26, 2019
1 parent 29fec04 commit 4b9b6a1
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/gatsby-image/.gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/*.js
/withIEPolyfill/*.js
yarn.lock
1 change: 1 addition & 0 deletions packages/gatsby-image/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
},
"dependencies": {
"@babel/runtime": "^7.0.0",
"object-fit-images": "^3.2.4",
"prop-types": "^15.6.1"
},
"devDependencies": {
Expand Down
51 changes: 51 additions & 0 deletions packages/gatsby-image/src/withIEPolyfill/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React, { Component, createRef, forwardRef } from "react"
import PropTypes from "prop-types"
import Image from "../index"

class ImageWithIEPolyfill extends Component {
imageRef = this.props.innerRef || createRef()

// Load object-fit/position polyfill if required (e.g. in IE)
componentDidMount() {
const testImg = document.createElement(`img`)
if (
typeof testImg.style.objectFit === `undefined` ||
typeof testImg.style.objectPosition === `undefined`
) {
import(`object-fit-images`).then(({ default: ObjectFitImages }) =>
ObjectFitImages(this.imageRef.current.imageRef.current)
)
}
}

render() {
const { objectFit, objectPosition, ...props } = this.props

return (
<Image
ref={this.imageRef}
{...props}
imgStyle={{
...props.imgStyle,
objectFit: objectFit,
objectPosition: objectPosition,
fontFamily: `"object-fit: ${objectFit}; object-position: ${objectPosition}"`,
}}
/>
)
}
}

ImageWithIEPolyfill.propTypes = {
objectFit: PropTypes.string,
objectPosition: PropTypes.string,
}

ImageWithIEPolyfill.defaultProps = {
objectFit: `cover`,
objectPosition: `50% 50%`,
}

export default forwardRef((props, ref) => (
<ImageWithIEPolyfill {...props} innerRef={ref} />
))
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -13148,6 +13148,11 @@ object-copy@^0.1.0:
define-property "^0.2.5"
kind-of "^3.0.3"

object-fit-images@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/object-fit-images/-/object-fit-images-3.2.4.tgz#6c299d38fdf207746e5d2d46c2877f6f25d15b52"
integrity sha512-G+7LzpYfTfqUyrZlfrou/PLLLAPNC52FTy5y1CBywX+1/FkxIloOyQXBmZ3Zxa2AWO+lMF0JTuvqbr7G5e5CWg==

object-hash@^1.1.4:
version "1.3.0"
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.0.tgz#76d9ba6ff113cf8efc0d996102851fe6723963e2"
Expand Down

0 comments on commit 4b9b6a1

Please sign in to comment.