Skip to content

Commit

Permalink
Add support for string width/height on Image component (#18178)
Browse files Browse the repository at this point in the history
For many users refactoring from `<img>` to `<Image>`, we can often support their properties as-is.
The exception was width/height.

This PR allows the `<Image>` component to accept strings for `width` and `height` just like `<img>`.

Related to #18122
  • Loading branch information
styfle committed Oct 24, 2020
1 parent 0dff7de commit 301c029
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 11 deletions.
24 changes: 15 additions & 9 deletions packages/next/client/image.tsx
Expand Up @@ -29,8 +29,8 @@ type ImageProps = Omit<
loading?: LoadingValue
unoptimized?: boolean
} & (
| { width: number; height: number; unsized?: false }
| { width?: number; height?: number; unsized: true }
| { width: number | string; height: number | string; unsized?: false }
| { width?: number | string; height?: number | string; unsized: true }
)

const imageData: ImageData = process.env.__NEXT_IMAGE_OPTS as any
Expand Down Expand Up @@ -229,16 +229,18 @@ export default function Image({
className = className ? className + ' __lazy' : '__lazy'
}

// No need to add preloads on the client side--by the time the application is hydrated,
// it's too late for preloads
const shouldPreload = priority && typeof window === 'undefined'

let divStyle: React.CSSProperties | undefined
let imgStyle: React.CSSProperties | undefined
let wrapperStyle: React.CSSProperties | undefined
if (typeof height === 'number' && typeof width === 'number' && !unsized) {
// <Image src="i.png" width=100 height=100 />
const quotient = height / width
if (
typeof height !== 'undefined' &&
typeof width !== 'undefined' &&
!unsized
) {
// <Image src="i.png" width={100} height={100} />
// <Image src="i.png" width="100" height="100" />
const quotient =
parseInt(height as string, 10) / parseInt(width as string, 10)
const ratio = isNaN(quotient) ? 1 : quotient * 100
wrapperStyle = {
maxWidth: '100%',
Expand Down Expand Up @@ -278,6 +280,10 @@ export default function Image({
}
}

// No need to add preloads on the client side--by the time the application is hydrated,
// it's too late for preloads
const shouldPreload = priority && typeof window === 'undefined'

return (
<div style={wrapperStyle}>
<div style={divStyle}>
Expand Down
2 changes: 1 addition & 1 deletion test/integration/image-component/default/pages/index.js
Expand Up @@ -5,7 +5,7 @@ const Page = () => {
return (
<div>
<p>Hello World</p>
<Image id="basic-image" src="/test.jpg" width={400} height={400}></Image>
<Image id="basic-image" src="/test.jpg" width="400" height="400"></Image>
<Image id="unsized-image" src="/test.png" unsized></Image>
<p id="stubtext">This is the index page</p>
</div>
Expand Down
6 changes: 6 additions & 0 deletions test/integration/image-component/default/test/index.test.js
Expand Up @@ -29,17 +29,23 @@ function runTests() {
const result = await browser.eval(
`document.getElementById('basic-image').naturalWidth`
)

if (result === 0) {
throw new Error('Incorrectly loaded image')
}

return 'result-correct'
}, /result-correct/)

await browser.eval(
'document.getElementById("unsized-image").scrollIntoView()'
)

await check(async () => {
const result = await browser.eval(
`document.getElementById('unsized-image').naturalWidth`
)

if (result === 0) {
throw new Error('Incorrectly loaded image')
}
Expand Down
8 changes: 7 additions & 1 deletion test/integration/image-component/typescript/pages/valid.tsx
Expand Up @@ -6,11 +6,17 @@ const Page = () => {
<div>
<p>Hello World</p>
<Image
id="with-and-height"
id="width-and-height-num"
src="https://via.placeholder.com/500"
width={500}
height={500}
></Image>
<Image
id="width-and-height-str"
src="https://via.placeholder.com/500"
width="500"
height="500"
></Image>
<Image
id="unsized-image"
src="https://via.placeholder.com/100"
Expand Down

0 comments on commit 301c029

Please sign in to comment.