NEXT Image: Shrinking inside flexbox with tailwind

3.4k views Asked by At

I am using NEXT Image component to Fit in with a flex box without shrinking. However, based on the content that is there in the other element, it keeps shrinking:

enter image description here

Here's my code:

import React from 'react';
import Image from 'next/image';
type Props = {
  imageUrl?: string;
  senderName: string;
  newMessageCount?: number;
  latestMessage: string;
};

export default function MessageBox({
  imageUrl,
  senderName,
  newMessageCount,
  latestMessage,
}: Props) {
  const isNewMessageDefined = newMessageCount ? true : false;
  const newMsgValue =
    latestMessage.length > 80
      ? `${latestMessage.slice(0, 80)}...`
      : latestMessage;
  return (
    <div className='flex w-full gap-2' aria-label='Funfuse-Message-Container'>
      <Image
        alt='Message Image'
        src={imageUrl ?? '/funfuse/avatar-02.jpg'}
        className='rounded-full shadow-lg shrink-0 shadow-indigo-500/50'
        height={80}
        width={80}
        objectFit='cover'
        objectPosition='center'
      />
      <div className='flex flex-col'>
        <div
          aria-label='Funfuse-Message-Header'
          className='flex flex-row items-center gap-2'>
          <h2 className='text-xl text-black'>{senderName ?? 'John Doe'}</h2>
          {isNewMessageDefined && (
            <div className='h-[1.2rem] w-[1.2rem] rounded-full relative bg-funfuse'>
              <label className='absolute text-xs text-white transform -translate-x-1/2 -translate-y-1/2 top-1/2 left-1/2'>
                {newMessageCount}
              </label>
            </div>
          )}
        </div>
        <div aria-label='Funfuse-Message-Body'>
          <label className='text-sm font-semibold text-gray-400'>
            {newMsgValue}
          </label>
        </div>
      </div>
    </div>
  );
}

Can someone help me identify how to prevent this issue as I always want my image to be of the size and never shrink. I tried using the property: flex-shrink: 0 but that didn't work too.

3

There are 3 answers

0
georgekpc On BEST ANSWER

Here is another fix that worked for me in a similar case. I wrapped the <Image /> component around a div with position: relative;width:80px;height:80px, removed width and height properties from the <Image /> component and added layout="fill" instead.

So instead of this

<Image
  alt='Message Image'
  src={imageUrl ?? '/funfuse/avatar-02.jpg'}
  className='rounded-full shadow-lg shrink-0 shadow-indigo-500/50'
  height={80}
  width={80}
  objectFit='cover'
  objectPosition='center'
/>

You would have something like this

<div className="relative w-[80px] h-[80px]">
 <Image
   alt='Message Image'
   src={imageUrl ?? '/funfuse/avatar-02.jpg'}
   className='rounded-full shadow-lg shrink-0 shadow-indigo-500/50'
   layout="fill"
   objectFit='cover'
   objectPosition='center'
 />
</div>
3
Eduardo Fortuna On

it may be because of the layout attribute in the default Image tag is responsive, it reduces its size when it reduces the width of the parent.

Set the layout fixed to keep the width of the image fixed. Here you can read more about next/image: https://nextjs.org/docs/api-reference/next/image

 return (
<div className='flex w-full gap-2' aria-label='Funfuse-Message-Container'>
  <Image
    alt='Message Image'
    src={imageUrl ?? '/funfuse/avatar-02.jpg'}
    className='rounded-full shadow-lg shrink-0 shadow-indigo-500/50'
    height={80}
    layout="fixed"
    width={80}
    objectFit='cover'
    objectPosition='center'
  />
  <div className='flex flex-col'>
    <div
      aria-label='Funfuse-Message-Header'
      className='flex flex-row items-center gap-2'>
      <h2 className='text-xl text-black'>{senderName ?? 'John Doe'}</h2>
      {isNewMessageDefined && (
        <div className='h-[1.2rem] w-[1.2rem] rounded-full relative bg-funfuse'>
          <label className='absolute text-xs text-white transform -translate-x-1/2 -translate-y-1/2 top-1/2 left-1/2'>
            {newMessageCount}
          </label>
        </div>
      )}
    </div>
    <div aria-label='Funfuse-Message-Body'>
      <label className='text-sm font-semibold text-gray-400'>
        {newMsgValue}
      </label>
    </div>
  </div>
</div>

);

0
theptrk On

Agree with answer from @georgekpc, you need to wrap the Image in a container

From the docs

The parent element must assign position: "relative", position: "fixed", or position: "absolute" style.

However, the layout prop is now deprecated and you need to use the fill prop as true.

    <div className="relative h-[56px] w-[56px]">
      <Image
        className="h-14 w-14 rounded-full"
        src={author.profileImageUrl}
        alt="Profile Image"
        fill={true}
      />
    </div>

https://nextjs.org/docs/pages/api-reference/components/image

https://nextjs.org/docs/pages/api-reference/components/image#fill