-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add container to render image as background behind children [WIP] #236
Conversation
As much as compatibility with the old version seems like a virtue here, I value symmetry and predictability in the interfaces for this library a great deal more. I'd rather we switch to using "nested" props for this, just like we now use nested props for everything else.
I think what you've got looks fine, but to be honest I'm not the best person to ask. My brain doesn't usually work in a tests-first fashion--I have to see the code and understand everything it's doing before I can think about what cases need to be covered by tests.
Let's skip it, and it can be added in the future if this is something lots of users would find useful.
This sounds like a no-brainer "yes" to me, so I'm thinking maybe there's something I'm not considering here. Is there a reason we wouldn't want to do this?
I think snapping to our srcset widths is a great idea. The height question is interesting, though. I don't like the idea of trying to shoehorn someone's specified height into a set of widths--what if we just generated a "height srcset" using the same algorithm as we use for generating widths and pick the correct image from there instead? |
I'm on board with all of these responses.
It's just something that wasn't implemented in the previous version, and will involve some more CSS (
Okay, I'll implement the snapping to widths. Can you elaborate more about what generating a height srcset when the user has passed a height would mean? The best strategy I can think of right now is: if a user passes in a width or a height, just calculate the other dimension given that dimension, and don't do any "magic". I think it would be confusing for a user, say, if we requested a different height than the height they specified. |
@jayeb although the tests are failing #thanksIE I'm happy with the implementation, and would love a review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A couple of changes, but this is definitely a step in the right direction. I assume react-imgix-old.js
is only in here to make dev easier, so I didn't review it.
Can you pull the .js
=> .jsx
conversion of the test file into a separate PR, or are there too many changes in there to cleanly separate?
README.md
Outdated
@@ -295,7 +299,44 @@ This works for Source and Picture elements as well. | |||
|
|||
#### Background mode | |||
|
|||
This feature has been removed from react-imgix when `sizes` and `srcset` was implemented. It was decided that it was too hard to implement this feature consistently. If you would still like to use this feature, please give this issue a thumbs up: [https://github.com/imgix/react-imgix/issues/160](https://github.com/imgix/react-imgix/issues/160) If we get enough requests for this, we will re-implement it. | |||
Images can be rendered as the background of a container around some children by using `<Background />`. The component will measure the natural size of the container as determined by the CSS on the page, and will render an optimal image for those dimensions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "around some children" part of this sentence is very confusing to me. Is there a way to convey this better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe it could use "behind" instead? Here are some options:
- Images can be rendered as a background behind children by using
<Background />
. <Background />
allows an image to be the background behind its children.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the first one best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is done.
README.md
Outdated
_For example_: | ||
|
||
```js | ||
<Imgix imgixParams={{ mask: "ellipse" }} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this example use <Background
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch
src/react-imgix-bg.jsx
Outdated
const noop = () => {}; | ||
|
||
const findNearestWidth = actualWidth => | ||
targetWidths.reduce((currentCandidate, candidateWidth) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the reduce
solution here, but isn't it pretty inefficient? It's gonna run through the entire list of widths every time, even if it finds the correct value after examining the very first candidate. I think a do-while would be better here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah it's inefficient. I'll investigate efficient ways to find the nearest value in a sorted list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replaced with a binary search which has O(log n) search complexity
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Frankly, this seems like overkill too! We know targetWidths
is sorted already, so can't we just do a simple while loop that checks each width starting from the lowest one and exits as soon as it finds one that's big enough?
src/react-imgix-bg.jsx
Outdated
const { w: forcedWidth, h: forcedHeight } = imgixParams; | ||
const hasDOMDimensions = contentRect.bounds.top != null; | ||
const htmlAttributes = props.htmlAttributes || {}; | ||
const dpr = imgixParams.dpr || window.devicePixelRatio || 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should round window.devicePixelRatio
to 2 decimal places here, since anything beyond 2 decimal places is disregarded by the painter and just hurts the cache.
src/react-imgix-bg.jsx
Outdated
width, | ||
height, | ||
fit: "crop", | ||
backgroundSize: "cover", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, isn't this accidentally adding &backgroundSize=cover
to all of our imgix URLs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops, don't know how this slipped in here.
…-imgix into fred/background-mode * 'fred/background-mode' of https://github.com/imgix/react-imgix: Sync with Prettier
src/react-imgix-bg.jsx
Outdated
|
||
const findNearestWidth = actualWidth => findClosest(actualWidth, targetWidths); | ||
|
||
const toFixed = (dp, value) => +value.toFixed(2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dp
is not used?
src/react-imgix-bg.jsx
Outdated
const { w: forcedWidth, h: forcedHeight } = imgixParams; | ||
const hasDOMDimensions = contentRect.bounds.top != null; | ||
const htmlAttributes = props.htmlAttributes || {}; | ||
const dpr = toFixed(2, imgixParams.dpr || window.devicePixelRatio || 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To support SSR:
const dpr = toFixed(2, imgixParams.dpr || window.devicePixelRatio || 1); | |
const dpr = toFixed(2, imgixParams.dpr || global.devicePixelRatio || 1); |
Co-Authored-By: frederickfogerty <frederick.fogerty@gmail.com>
Thanks for the very helpful review @adamraider. The tests pass locally but there are just a few issues remaining with IE 11 that I need to investigate before merging this. |
…-imgix into fred/background-mode * 'fred/background-mode' of https://github.com/imgix/react-imgix: Sync with Prettier
Description
This PR adds a new React component which enables an image to be rendered as a background behind children components.
This used to exist in this library before a previous update removed it. Because of the community support in #160, it has been re-implemented.
I've opened this PR early to gain feedback.
TODO
Discussion Points
width
andheight
be top-level props (or just props inhtmlAttributes
andimgProps
)? This was available in the old implementation, so it'd be a +1 to be compatible with that. This is at odds with the strategy taken by this library currently which is to try limit the number of top-level props.onMounted
prop? We have aonLoad
for ourimg
tag, but this only makes sense because there is an equivalent attribute for a nativeimg
tag. I'm thinking we shouldn't.New Feature
feat(<area>): added new way to do this cool thing #issue-number
Steps to Test
Review changes to unit tests.