Next/Image Onload Event reports zero natural height and width when lazy in Firefox
Verify canary release
- [X] I verified that the issue exists in Next.js canary release
Provide environment information
next:12.1.1-canary.1 node: v16.13.2
What browser are you using? (if relevant)
Firefox 97.0.1
How are you deploying your application? (if relevant)
npm run dev
Describe the Bug
Hello and thanks again for merging my 2nd pull request!
Currently I have a strange but annoying issue, not sure if it's only browser related. When I use onLoadingComplete I get wrong naturalWidth and naturalHeight properties, they are both zero or one. That happens currently ONLY in FIrefox and ONLY when the image loads lazily e.g. when scrolling to its position. Adding "priority" prop or switching browser, the issue dissapears. Any ideas? I need those numbers to be correct in order to calibrate the parent container with the correct aspect ratio for resizing purposes.
Expected Behavior
OnLoading complete should report correct naturalHeight and naturalwIdth in every case.
To Reproduce
<Image
src={imageLocation}
onLoadingComplete={(e)=>console.log(e.naturalHeight)}
layout="fill"
/>
Given your reproduction, I could not see an issue in any browsers (as in height was reported correctly). Could you add a more complete reproduction? :pray:
I tried:
import Image from "next/image"
import img from "../public/logo.png"
export default function Home() {
return (
<>
<div style={{ height: 2000 }} />
<div style={{ position: "relative", height: "500px", width: "500px" }}>
<Image
src={img}
onLoadingComplete={(e) => console.log(e)}
layout="fill"
/>
</div>
</>
)
}
Hello again, even when I import the image locally, the issue persists. This is the full code of my component, the same of course happens with any other component as well. Maybe I'll try with a clean new next project, still it does not make any sense.
import Image from "next/image";
import Link from "next/link";
import { useRef, useState } from "react";
import styles from "./Banner.module.scss";
declare type ImgElementStyle = NonNullable<
JSX.IntrinsicElements["img"]["style"]
>;
export interface IBannerProps {
imageLocation: string;
navLocation: string;
header1?: string;
header2?: string;
header3?: string;
buttonTitle: string;
objectFit?: ImgElementStyle["objectFit"];
objectPosition?: ImgElementStyle["objectPosition"];
preload?: boolean;
}
const Banner: React.VFC<IBannerProps> = ({
imageLocation,
navLocation,
header1,
header2,
header3,
buttonTitle,
objectFit = "cover",
objectPosition = "center",
preload = false,
}) => {
const [padding, setPadding] = useState(0);
return (
<div
className={styles.bannerContainer}
style={{ paddingTop: padding + "%" }}
>
<div className={styles.mainSection}>
<h3 className={styles.header1}>{header1}</h3>
<h1 className={styles.header2}>{header2}</h1>
<h2 className={styles.header3}>{header3}</h2>
<Link href={navLocation}>
<a className={styles.introButton}>{buttonTitle}</a>
</Link>
</div>
<Image
// lazyRoot={myRef}
src={img}
alt={header2}
onLoadingComplete={(e) => {
console.log(e.naturalHeight, e.naturalWidth);
if (padding === 0)
setPadding(100 * (e.naturalHeight / e.naturalWidth));
}}
priority
layout="fill"
//priority={true}
/>
</div>
);
};
export default Banner;
Given your reproduction, I could not see an issue in any browsers (as in height was reported correctly). Could you add a more complete reproduction? 🙏
I tried:
import Image from "next/image" import img from "../public/logo.png" export default function Home() { return ( <> <div style={{ height: 2000 }} /> <div style={{ position: "relative", height: "500px", width: "500px" }}> <Image src={img} onLoadingComplete={(e) => console.log(e)} layout="fill" /> </div> </> ) }
I noticed that the problem is when using more than one Images, please try to reproduce the following. I tried with a fresh create-next-app as mentioned above, still the issue persists, only with lazy loading and only on firefox.
<Image src={"/image3.jpg"} alt="image" layout="fill" onLoadingComplete={e=>console.log(e)}/> <Image src={"/image2.jpg"} alt="image" layout="fill" onLoadingComplete={e=>console.log(e)}/> <Image src={"/image1.jpg"} alt="image" layout="fill" onLoadingComplete={e=>console.log(e)}/>
Hello again,
After playing with the above, a far more SERIOUS issue has emerged and I would like your help. Image "priority" option is not working always, meaning that it does not always preload the Image putting the corresponding "preload" tag in document's head. That happens if instead of including directly the Image component in my page, I import a component which then includes Image. for example when I have:
<Carousel imageLocation="/image1.jpg".../> and Inside the Carousel component I have: <Image src={imageLocation} priority .../>
the Image does NOT preload. It only preloads if I have <Image src="image1.jpg" priority .../> DIRECTLY inside my page. Is there any known issue that I am not aware about? Also, should I open a new issue for the above case? Thanks
Could you please open a separate bug report for a separate issue, with a minimal reproduction attached? :pray:
Small update here, we think we discovered a browser bug here. It looks like I was able to reproduce the issue without Next.js, and only in Firefox. Reported it here: https://bugzilla.mozilla.org/show_bug.cgi?id=1758035
Will keep you posted.
Great, I have already watched the comments, thank you!
Looks more like this one - https://bugzilla.mozilla.org/show_bug.cgi?id=1607081 Though they're probably related.
I had the same issue, and setting position: relative to image parent helped
seems like the reason of balazsorban44 having it working is that he put position: relative, and 11koukou didn't
might help as it did to me
PS: and yeah, it persists in Firefox only, e.g. Chrome does not respond to this tiny change