-
I'm using nextjs 10.0.1-canary-6 with the new fill layout that replaces the unsized prop and i just want to set a maximum height and width for my image but it just isn't possible: Update: still applies to 10.0.1 import React from "react";
import Image from "next/image";
function test() {
return (
<div
style={{
width: "200px",
height: "200px",
maxHeight: "200px",
maxWidth: "200px",
}}
>
<Image
src={"renders/KMxNJT7MKtCGg7QkpKCL/KMxNJT7MKtCGg7QkpKCL.png"}
layout="fill"
style={{
width: "200px",
height: "200px",
maxHeight: "200px",
maxWidth: "200px",
}}
/>
</div>
);
}
export default test; The image component doesn't respect ANY styling that restricts dimensions. It's literally as big as the whole page! |
Beta Was this translation helpful? Give feedback.
Replies: 33 comments 63 replies
-
You have to configure position relative for the parent. Could you please try that and let us know? <div
style={{
position: "relative",
width: "200px",
height: "200px",
maxHeight: "200px",
maxWidth: "200px",
}}
> |
Beta Was this translation helpful? Give feedback.
-
Adding position relative does work but in this case it seems that you need width and height attributes. For example if I remove width and height attributes and just leave maxWidth and maxHeight: function test() {
return (
<div
style={{
position: "relative",
maxHeight: "200px",
maxWidth: "200px",
}}
>
<Image
src="renders/KMxNJT7MKtCGg7QkpKCL/KMxNJT7MKtCGg7QkpKCL.png"
layout="fill"
/>
</div>
);
} I would expect the image to "fill" the available space. But instead, the image is 0x0 big: Even if i explicitly set width and height to 100% the result stays the same: <div
style={{
position: "relative",
maxHeight: "200px",
maxWidth: "200px",
}}
>
<Image
src="renders/KMxNJT7MKtCGg7QkpKCL/KMxNJT7MKtCGg7QkpKCL.png"
layout="fill"
style={{ width: "100%", height: "100%" }}
/>
</div> But if I use the normal img tag, everything behaves as expected: function test() {
return (
<div
style={{
position: "relative",
maxHeight: "200px",
maxWidth: "200px",
}}
>
<img
style={{ width: "100%", height: "100%" }}
src="https://images.unsplash.com/photo-1604321951949-e9d5710716db?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3578&q=80"
/>
</div>
);
} |
Beta Was this translation helpful? Give feedback.
-
Ok so codesandbox seems to have problems installing the next.js canary and actually rendering anything but I managed to deploy it to vercel: https://csb-i3hk3-8a8ckr8o5.vercel.app/ And here's the sandbox: https://codesandbox.io/s/quizzical-shannon-i3hk3?file=/pages/index.js |
Beta Was this translation helpful? Give feedback.
-
What are you trying to get the image to do? |
Beta Was this translation helpful? Give feedback.
-
I just want the image to not exceed certain dimensions. Basically I want an image container that the image is not allowed to exceed, I also don't want to set the width and height on the image itself because I don't know the exact dimensions ahead of time, hence I need to use layout="fill". So just what the canary 6 docs describe really (https://github.com/vercel/next.js/blob/canary/docs/api-reference/next/image.md)
|
Beta Was this translation helpful? Give feedback.
-
Have you tried using |
Beta Was this translation helpful? Give feedback.
-
yes but responsive requires you to set width and height which I don't want to set because I don't know what the aspect ratio is going to be |
Beta Was this translation helpful? Give feedback.
-
Yes,
Is there a way to have same behavior as it had with |
Beta Was this translation helpful? Give feedback.
-
I'm in this, the dimensions of my image are not known and when I use the fill layout, it stretches in both dimensions. What I really want to generate is the largest image on the display that is being shown without stretching the image. |
Beta Was this translation helpful? Give feedback.
-
How about this? <Image
src={"renders/KMxNJT7MKtCGg7QkpKCL/KMxNJT7MKtCGg7QkpKCL.png"}
objectFit={"cover"}
width={200}
height={200}
/> |
Beta Was this translation helpful? Give feedback.
-
like that https://user-images.githubusercontent.com/48503371/98456358-72669c80-215b-11eb-9e6b-3ec6643c7a85.png |
Beta Was this translation helpful? Give feedback.
-
Did you solve this? Property "fill" always fits to the viewport & not to parent element as expected. In 10.0.0 unsized worked good, but layout="fill" 's behavior is not the same. |
Beta Was this translation helpful? Give feedback.
-
Same here. In version 10.0.0 the new I understand the preference to not have this content shift by default, but the previous behaviour (and how I think everyone expects the Also, isn't this a breaking change? On version 10.0.0 the |
Beta Was this translation helpful? Give feedback.
-
Hey @Timer, I am well aware of the layout shift problem the next image is trying to solve, but for some projects I want to leverage the next image component for the dynamic optimization of the image (creation of multiple versions, srcset, sizes etc.). Something like: const getDim = (url, callback) => {
var img = new Image();
img.src = url;
img.onload = function () {
callback(this.width, this.height);
};
};
const ResponsiveImage = ({ src }) => {
const [width, setWidth] = useState();
const [height, setHeight] = useState();
const [loaded, setLoaded] = useState(false);
useEffect(() => {
getDim(src, function (w, h) {
setLoaded(true);
setWidth(w);
setHeight(h);
});
}, [src]);
if (!loaded || !width || !height) {
return "";
}
return (
<ImageWrapper>
<NextImage
src={src}
quality="85"
width={width}
height={height}
/>
</ImageWrapper>
);
}; It would be really awesome to not have to specify the dimensions in advance. Let me know if I can help in any way. |
Beta Was this translation helpful? Give feedback.
-
I think you should bring back the For example, I want a vertical gallery, each image On a more general note, I think the overall design of this component should be updated. It should first be a drop-in replacement of HTML Then if you want to add extra features, great and I agree it saves us a lot of time, but they should not have to be enforced on an API level. |
Beta Was this translation helpful? Give feedback.
-
Any updates on this? I'm still having this issue. |
Beta Was this translation helpful? Give feedback.
-
Hi Guys I got my image to fill the entire width of the parent container & maintaining the image's aspect ratio by fiddling with the default css next/image adds. Might not be too pretty but it's all I can find to work. Hope this helps someone Next 12 Update: JS
CSS
|
Beta Was this translation helpful? Give feedback.
-
Base on @arnovanstaden 's solution, I've created this Image componeng that is truely "fill" layout import NextImage from 'next/image';
import React from 'react';
import {
flexbox,
FlexboxProps,
height,
HeightProps,
margin,
MarginProps,
maxHeight,
MaxHeightProps,
maxWidth,
MaxWidthProps,
padding,
PaddingProps,
width,
WidthProps,
} from 'styled-system';
import styled from '@emotion/styled';
const ImageContainer = styled.div<HeightProps & WidthProps & MaxHeightProps & MaxWidthProps>`
> div {
&:first-child {
position: unset !important;
}
margin-top: ${(props) => props.theme.heights.navbar};
max-height: ${(props) => props.height};
width: ${(props) => props.width};
}
display: flex;
${height}
${width}
${maxHeight}
${maxWidth}
`;
const BaseImage = styled(NextImage)`
object-fit: cover;
width: 100% !important;
position: relative !important;
height: unset !important;
`;
const ImageOverlay = styled.div<PaddingProps & MarginProps & FlexboxProps>`
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
padding: 1.25rem;
color: ${(props) => props.color};
text-decoration: none;
${padding}
${margin}
${flexbox}
`;
type ImageProps = React.ComponentProps<typeof ImageContainer> &
Omit<React.ComponentProps<typeof NextImage>, 'width' | 'height'>;
const Image = (props: ImageProps) => {
const { width, height, maxHeight, maxWidth, children, ...rest } = props;
return (
<ImageContainer width={width} height={height} maxHeight={maxHeight} maxWidth={maxWidth}>
<BaseImage layout="fill" {...rest} />
{children && <ImageOverlay>{children}</ImageOverlay>}
</ImageContainer>
);
};
export default Image; |
Beta Was this translation helpful? Give feedback.
-
Anyone looking for a video explanation, here is a video showing how to implement the solution @arnovanstaden shared |
Beta Was this translation helpful? Give feedback.
-
Is this issue still exists after next@11 release |
Beta Was this translation helpful? Give feedback.
-
Problem with existing solution for next@11 that it is pretty hard to manage, for example, having a lot of different combinations widths, heights and positions on the page. |
Beta Was this translation helpful? Give feedback.
-
Hey! Found a solution with Here is the full code of the custom
Hope it helps! |
Beta Was this translation helpful? Give feedback.
-
Does the issue still exists with Next 12? |
Beta Was this translation helpful? Give feedback.
-
does the fix here still work with Next 12? I just upgraded and it doesn't seem to do the trick anymore! Anyone else? |
Beta Was this translation helpful? Give feedback.
-
Oh, I think I figured it out. In Next 12 the
now needs to be
|
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
When I used the solutions above, I had the issue that the container was bigger than the image. For my use case the container had to be exactly the size the image will use. This snippet has one downside , you need to pass the original resolution of the image to the component. import * as React from 'react';
import NextImage from 'next/image';
type Props = {
src: string;
//resolution of the source file
resHeight: number;
resWidth: number;
//desired height/width
height?: number | string;
width?: number | string;
//specify whether the height or width value should be used to size the image. Useless unless both width and height are specified. Default: height.
resizeBy?: 'height' | 'width';
};
export const Image = (props: Props) => {
const resizeBy = props.resizeBy || props.height ? 'height' : 'width';
if (!props[resizeBy]) throw new Error('either height or width have to be specified');
const parsedHeight = parseDimension(props.height);
const parsedWidth = parseDimension(props.width);
const suffix = resizeBy == 'height' ? parsedHeight.suffix : parsedWidth.suffix;
const renderedHeight = resizeBy == 'height' ? parsedHeight.value : props.resHeight / (props.resWidth / parsedWidth.value);
const renderedWidth = resizeBy == 'width' ? parsedWidth.value : props.resWidth / (props.resHeight / parsedHeight.value);
return (
<div style={{ position: 'relative', height: `${renderedHeight}${suffix}`, width: `${renderedWidth}${suffix}` }}>
<NextImage src={props.src} layout={'fill'} />
</div>
);
};
/**
* parses a height/value into a object that is easier to handle
* Examples:
* - 24 -> {value: 24, suffix: ''}
* - "24rem" -> {value: 24, suffix: 'rem'}
* @param value the value to be parsed
*/
function parseDimension(value: number | string | undefined): { value: number; suffix: string } {
if (value == undefined) return { value: 0, suffix: '' };
if (typeof value == 'number') return { value, suffix: '' };
let split = value.split(/(\d+)/).filter(el => el != ''); //should have format [number, string | undefined]
if (split.length == 0) throw new Error('height/width cannot be 0');
if (isNaN(Number(split[0]))) throw new Error('height/width have to begin with a number');
if (split.length > 2) throw Error("width/height has to be a number or have the format '\\d+\\w*'");
return { value: Number(split[0]), suffix: split[1] ?? '' };
} It can be used like this <div style={{ height: '24rem', width: '100%', display: 'flex', justifyContent: 'start' }}>
<Image src="/images/b9eb0b22727b693b1ff8ac6c15ecb18994cf7e7680425e87ecbde543e62c0d21.png" height={'24rem'} resHeight={2160} resWidth={1800} />
<Image src="/images/b9eb0b22727b693b1ff8ac6c15ecb18994cf7e7680425e87ecbde543e62c0d21.png" height={'24rem'} resHeight={2160} resWidth={1800} />
</div> Edit: Sorry for editing this message so often |
Beta Was this translation helpful? Give feedback.
-
Any news on this issue? I've been unable to find a way to display images of variable heights without ending up with letterboxes around my images. :\ In my case I'm pulling multiple images from markdown content and displaying them using |
Beta Was this translation helpful? Give feedback.
-
Edit: Next.js 13 introduces a new & improved Image component based on feedback like this! |
Beta Was this translation helpful? Give feedback.
-
Hi everyone, is there a way to put the width of the parent and an auto height? |
Beta Was this translation helpful? Give feedback.
Edit: Next.js 13 introduces a new & improved Image component based on feedback like this!
http://nextjs.org/13