homeaboutvideotry it nowpricingdocs
Guide

Crop user avatars and thumbnails to a fixed size

Users upload photos in every shape. Get a consistent square out of all of them.

The problem

A grid of avatars looks wrong the moment one is a tall portrait and another is a wide landscape. Forcing the shape in CSS with object-fit helps, but you still download the full upload, and you cannot control where the crop lands.

Doing it on the server side of the image is better: the browser receives an image that is already the right shape and size, and a phone does not download a 6 MB photo to show a 48 pixel circle.

Option 1: resize with cover

The simplest approach is a fixed box with fit:cover. The image is scaled to fill the box and the overflow is cropped. Use position to choose which edge to favour.

?transform=resize:200x200~fit:cover
?transform=resize:200x200~fit:cover~position:top

position:top is useful for portraits, where the face is usually in the upper part of the frame.

Option 2: show the whole image on a plain background

When nothing may be cut off, such as logos or product shots, use fit:contain. The whole image is scaled to fit and the leftover space is filled with a colour. Colours use hex(...) with 3, 6 or 8 digits.

?transform=resize:200x200~fit:contain~background:hex(fff)

Which crop to use

  • Avatars and cards: fit:cover, with position:top for portraits.
  • Logos and product images: fit:contain with a background colour.
  • Exact pixel size, any shape: fit:fill stretches the image, so use it only when distortion does not matter.
  • Logos and product shots with white space: trim first to cut the plain border away, then fit:contain.
  • A chosen crop region: save the point that matters (from a crop tool in your uploader, say) and pass it as ~focus:X,Y on the resize, or crop exactly with crop:WxH@X,Y.
  • Face detection: the image service does not detect faces. smartCrop picks the most detailed part of the image, which often but not always includes the face.

In React

Avatar.tsx
import { Image } from "@cd2/fileboy-react"

export function Avatar({ fileId, size = 48 }: { fileId: string; size?: number }) {
  // Ask for twice the displayed size so it stays sharp on high-density screens.
  const pixels = size * 2

  return (
    <Image
      id={fileId}
      transforms={[
        { type: "resize", width: pixels, height: pixels, fit: "cover", position: "top" },
        { type: "format", format: "webp" },
        { type: "quality", value: 80 },
      ]}
      imgProps={{ width: size, height: size, alt: "", style: { borderRadius: "50%" } }}
    />
  )
}

The same pattern builds thumbnails of any shape: change the transform and the size, and keep the stored file ID the same. Because the original is untouched, you can change the avatar size across your whole app in one edit.

From your server

Emails, APIs and server-rendered pages need the URL without React. Build it with the client for your language, using the same resize and fit options.

const avatar = fileboy.buildImageUrl(photoId, {
  transforms: [{ type: "resize", width: 200, height: 200, fit: "cover" }],
})

Checked against the current libraries in November 2026. Found something that no longer works? Tell us.

Go deeper

Still choosing a tool?

Fileboy is small on purpose. This comparison says where it fits and where another option is the better call.

Fileboy vs Cloudinary · All comparisons

Try it

The free plan needs no card and includes 1,000 files, so you can run every example above.

More guides: How to add image upload to a React app · Resize images on the fly with a URL · Stream video with HLS without running ffmpeg · Add captions and subtitles to a video · All guides

Add Fileboy to your next project

We built Fileboy to stop rebuilding file handling for every app. Create an app, paste your key and upload a file. The free plan needs no card.