diff --git a/packages/next/client/image.tsx b/packages/next/client/image.tsx
index 78e263d0aa5bb..951d8c60c6d61 100644
--- a/packages/next/client/image.tsx
+++ b/packages/next/client/image.tsx
@@ -245,6 +245,7 @@ function defaultImageLoader(loaderProps: ImageLoaderProps) {
function handleLoading(
img: HTMLImageElement | null,
src: string,
+ layout: LayoutValue,
placeholder: PlaceholderValue,
onLoadingComplete?: OnLoadingComplete
) {
@@ -267,6 +268,18 @@ function handleLoading(
// underlying DOM element because it could be misused.
onLoadingComplete({ naturalWidth, naturalHeight })
}
+ if (process.env.NODE_ENV !== 'production') {
+ const parent = img.parentElement?.parentElement?.style
+ if (layout === 'responsive' && parent?.display === 'flex') {
+ console.warn(
+ `Image with src "${src}" may not render properly as a child of a flex container. Consider wrapping the image with a div to configure the width.`
+ )
+ } else if (layout === 'fill' && parent?.position !== 'relative') {
+ console.warn(
+ `Image with src "${src}" may not render properly with a parent using position:"${parent?.position}". Consider changing the parent style to position:"relative" with a width and height.`
+ )
+ }
+ }
})
}
}
@@ -612,7 +625,7 @@ export default function Image({
className={className}
ref={(img) => {
setRef(img)
- handleLoading(img, srcString, placeholder, onLoadingComplete)
+ handleLoading(img, srcString, layout, placeholder, onLoadingComplete)
}}
style={{ ...imgStyle, ...blurStyle }}
/>
diff --git a/test/integration/image-component/default/pages/layout-fill-inside-nonrelative.js b/test/integration/image-component/default/pages/layout-fill-inside-nonrelative.js
new file mode 100644
index 0000000000000..b446248761640
--- /dev/null
+++ b/test/integration/image-component/default/pages/layout-fill-inside-nonrelative.js
@@ -0,0 +1,13 @@
+import React from 'react'
+import Image from 'next/image'
+import img from '../public/test.jpg'
+
+const Page = () => {
+ return (
+
+
+
+ )
+}
+
+export default Page
diff --git a/test/integration/image-component/default/pages/layout-responsive-inside-flex.js b/test/integration/image-component/default/pages/layout-responsive-inside-flex.js
new file mode 100644
index 0000000000000..923c9810cb174
--- /dev/null
+++ b/test/integration/image-component/default/pages/layout-responsive-inside-flex.js
@@ -0,0 +1,13 @@
+import React from 'react'
+import Image from 'next/image'
+import img from '../public/test.jpg'
+
+const Page = () => {
+ return (
+
+
+
+ )
+}
+
+export default Page
diff --git a/test/integration/image-component/default/test/index.test.js b/test/integration/image-component/default/test/index.test.js
index aff13d076e6ff..555a2f134fe4c 100644
--- a/test/integration/image-component/default/test/index.test.js
+++ b/test/integration/image-component/default/test/index.test.js
@@ -582,6 +582,33 @@ function runTests(mode) {
)
})
+ it('should warn when img with layout=responsive is inside flex container', async () => {
+ const browser = await webdriver(appPort, '/layout-responsive-inside-flex')
+ await browser.eval(`document.getElementById("img").scrollIntoView()`)
+ const warnings = (await browser.log('browser'))
+ .map((log) => log.message)
+ .join('\n')
+ expect(await hasRedbox(browser)).toBe(false)
+ expect(warnings).toMatch(
+ /Image with src (.*)jpg(.*) may not render properly as a child of a flex container. Consider wrapping the image with a div to configure the width/gm
+ )
+ })
+
+ it('should warn when img with layout=fill is inside a container without position relative', async () => {
+ const browser = await webdriver(
+ appPort,
+ '/layout-fill-inside-nonrelative'
+ )
+ await browser.eval(`document.getElementById("img").scrollIntoView()`)
+ const warnings = (await browser.log('browser'))
+ .map((log) => log.message)
+ .join('\n')
+ expect(await hasRedbox(browser)).toBe(false)
+ expect(warnings).toMatch(
+ /Image with src (.*)jpg(.*) may not render properly with a parent using position:\\"static\\". Consider changing the parent style to position:\\"relative\\"/gm
+ )
+ })
+
it('should warn when using a very small image with placeholder=blur', async () => {
const browser = await webdriver(appPort, '/small-img-import')