Skip to content

✨ Feature request — Add a maxWidth (and maxHeight) option alongside maxWidthOrHeight #231

@Zyron

Description

@Zyron

At the moment the library only exposes

maxWidthOrHeight: number

which caps the larger side of the image.
Many use-cases (e.g. event‐card thumbnails, fixed-width avatars, or CMS “hero” banners) need to clamp the width only while letting the height be proportional and unrestricted.

Adding a dedicated

maxWidth?: number
maxHeight?: number

—applied before maxWidthOrHeight—would give developers finer control without breaking the current API.

Why this matters
• Thumbnails with consistent width: When we show a grid of cards the width must be the same, but portrait shots should keep their full height so the subject isn’t over-cropped.
• Bandwidth optimisation: Services like Supabase bill egress; sending a 600 px-wide portrait that’s auto-shrunk to 450 px because the height was 600 px first wastes ~30 % bandwidth.
• Parity with server tools: Popular back-end libraries (sharp, imagemagick) already support independent width/height constraints, so adding it here avoids double-pass processing.

Proposed behaviour
1. If maxWidth OR maxHeight is supplied, apply those first (respecting aspect ratio, no upscaling).
2. If maxWidthOrHeight is also supplied, perform the existing “largest side” clamp on the already-resized image.
3. If multiple constraints conflict, pick the most restrictive to keep backwards compatibility.

Pseudo-flow:

if (maxWidth || maxHeight) {
// shrink to fit within those bounds while preserving aspect ratio
}
if (maxWidthOrHeight) {
// then ensure the largest side ≤ maxWidthOrHeight
}

API surface (TypeScript)

export interface Options {
maxWidth?: number; // new
maxHeight?: number; // new
maxWidthOrHeight?: number;
// … rest unchanged
}

Both new props can be optional; existing code continues to work untouched.

Interest & prior art
• At least several open issues (#231, #256, #314) and StackOverflow questions request width-only resizing.
• Packages like compressorjs already expose maxWidth/maxHeight.

Workaround (today)

We currently have to:

const tmp = await imageCompression(file, { maxWidthOrHeight: 600 });
/* later on server: sharp(buffer).resize({ width: 600 }) */

which does two passes and still uploads a larger file than necessary.

Thanks for the great library! Happy to prepare a PR if this sounds acceptable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions