From 94e135c5222b44d538c4d0e74633db181e53e07d Mon Sep 17 00:00:00 2001 From: Alex Castle Date: Mon, 16 Sep 2024 16:58:31 -0700 Subject: [PATCH] feat: add sizes=auto fallback --- README.md | 18 +++++++- src/react-imgix.jsx | 12 ++++- test/unit/react-imgix.test.jsx | 84 ++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2c511311..4ad86d9c 100644 --- a/README.md +++ b/README.md @@ -585,7 +585,23 @@ For example, if the the developer would like to attach a custom `onLoad` callbac #### Lazy Loading -If you'd like to lazy load images, we recommend using [lazysizes](https://github.com/aFarkas/lazysizes). In order to use react-imgix with lazysizes, you can simply tell it to generate lazysizes-compatible attributes instead of the standard `src`, `srcset`, and `sizes` by changing some configuration settings: +If you'd like to lazy load images, we recommend using browser-level lazy loading, with the [`loading`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/loading) property, passed in `htmlAttributes`: + +```jsx + +``` + +This property has [strong browser support](https://caniuse.com/loading-lazy-attr), and functions without additional JavaScript. Additionally, using browser-level lazy loading enables optimization of the sizes attribute with `sizes="auto"`, which allows the browser to [automatically calculate the optimal size](https://ericportis.com/posts/2023/auto-sizes-pretty-much-requires-width-and-height/) for the image based on its layout. + +If you need granular control over lazy-loading behavior such as loading distance, you can use the [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API). + +If you are using a library like [lazysizes](https://github.com/aFarkas/lazysizes), you can tell the Imgix component to generate compatible attributes instead of the standard `src`, `srcset`, and `sizes` by changing some configuration settings: ```jsx { "data-src": "https://mysource.imgix.net/demo.png", width: "200", height: "100", + loading: "lazy" }; sut = shallow( { expect(sut.props()["data-src"]).toEqual(htmlAttributes["data-src"]); expect(sut.props()["width"]).toEqual(htmlAttributes["width"]); expect(sut.props()["height"]).toEqual(htmlAttributes["height"]); + expect(sut.props()["loading"]).toEqual(htmlAttributes["loading"]); + }); + it("prepends 'auto, ' to the sizes prop if loading is lazy and not fixed size", () => { + const htmlAttributes = { + "data-src": "https://mysource.imgix.net/demo.png", + width: "200", + loading: "lazy", + }; + sut = shallow( + + ); + expect(sut.props()["sizes"]).toEqual("auto, 100vw"); + }); + + it("does not prepend 'auto, ' to the sizes prop if loading is not lazy", () => { + const htmlAttributes = { + "data-src": "https://mysource.imgix.net/demo.png", + width: "200", + height: "100", + loading: "eager", // Not lazy loading + }; + sut = shallow( + + ); + expect(sut.props()["sizes"]).toEqual("100vw"); + }); + + it("does not prepend 'auto, ' to the sizes prop if loading is omitted", () => { + const htmlAttributes = { + "data-src": "https://mysource.imgix.net/demo.png", + width: "200", + height: "100", + }; + sut = shallow( + + ); + expect(sut.props()["sizes"]).toEqual("100vw"); + }); + + it("does not prepend 'auto, ' to the sizes prop if both width and height are present (htmlAttributes)", () => { + const htmlAttributes = { + "data-src": "https://mysource.imgix.net/demo.png", + width: "200", + height: "100", + loading: "lazy", + }; + sut = shallow( + + ); + expect(sut.props()["sizes"]).toEqual("100vw"); + }); + + it("does not prepend 'auto, ' to the sizes prop if both width and height are present (element attributes)", () => { + const htmlAttributes = { + "data-src": "https://mysource.imgix.net/demo.png", + loading: "lazy", + }; + sut = shallow( + + ); + expect(sut.props()["sizes"]).toEqual("100vw"); }); }); });