DEV Community

Cover image for Why I Built ngx-smart-cropper (and What Most Angular Image Croppers Get Wrong)
Kurt Van den Branden
Kurt Van den Branden

Posted on

Why I Built ngx-smart-cropper (and What Most Angular Image Croppers Get Wrong)

If you’ve built Angular apps that let users upload images, sooner or later you’ll run into the need to crop them. Most solutions out there work, but they often fall short in real-world use cases.

That’s exactly what led me to create ngx-smart-cropper, a lightweight image cropper built as a standalone Angular component that’s easy to integrate and works great in real apps.
https://github.com/kurti-vdb/ngx-smart-cropper


The problem with existing Angular croppers

Most image croppers for Angular suffer from at least one of these issues:

  • Heavy dependencies or bloated bundles — even for simple cropping
  • Not Angular-native APIs — imperative hooks instead of declarative bindings
  • Poor mobile experience — dragging and resizing feels laggy or unpredictable
  • Hard to style — locked-in CSS or inline styles you end up fighting

After using several libraries in multiple projects, I found none that hit the sweet spot of performance, control, simplicity, and polish.


What ngx-smart-cropper gets right

ngx-smart-cropper was built to solve real pain points.

Angular-native API

It uses plain Angular inputs and outputs.
No services. No global configuration. No magic.

You bind state and react to events. Angular stays in control.


Predictable UI

You have full control over:

  • crop position
  • crop size
  • aspect ratio
  • theme (auto light, dark, or mixed)

Nothing resizes itself unexpectedly. Nothing jumps around.


Responsive and touch-friendly

Touch interaction was not added as an afterthought.

Dragging and resizing work smoothly on real mobile devices, not just desktop emulators.
This matters more than most cropper demos admit.


Lightweight by design

No large external dependencies.
No unnecessary abstraction layers.

The goal was simple: stay small, stay fast, stay out of the way.


It actually looks good (and that’s intentional)

Let’s be honest for a moment.

Most image croppers technically work, but visually they look like something pulled straight out of 2012. Heavy borders, awkward handles, aggressive overlays, and UI you immediately want to hide.

ngx-smart-cropper was designed with the assumption that this component will be visible to end users, not just developers.

That means:

  • Clean, modern visuals out of the box
  • Subtle overlays that don’t fight the image
  • Crop handles that feel precise, not clumsy
  • A UI that looks just as good in admin dashboards as in consumer-facing apps

In short: it’s intentionally good-looking.

You don’t need to restyle it just to make it acceptable.
You style it because you want to.

If you care about UX polish, not just functionality, this matters more than most libraries admit.


Installation and quick start

Install it from npm:

npm install ngx-smart-cropper
Enter fullscreen mode Exit fullscreen mode

Use it as a standalone component:

<input
  type="file"
  accept="image/*"
  (change)="onFileChange($event)"
>

<ngx-smart-cropper
  [imageType]="'jpeg'"
  [aspectRatio]="1"
  [cropX]="50"
  [cropY]="50"
  [cropWidth]="250"
  [cropHeight]="250"
  [theme]="'mixed'"
  [imageSource]="imageSource"
  (imageCroppedEvent)="imageCropped($event)"
></ngx-smart-cropper>

<img [src]="croppedImage" />
Enter fullscreen mode Exit fullscreen mode

And in your component:

import { ImageCropperComponent } from 'ngx-smart-cropper';
import { Component } from '@angular/core';

@Component({
  standalone: true,
  imports: [ImageCropperComponent],
  selector: 'my-component',
  templateUrl: './my-component.html'
})
export class MyComponent {
  croppedImage = '';
  imageSource: string | null = null;

  onFileChange(event: Event): void {
    const input = event.target as HTMLInputElement;
    if (!input.files?.length) return;

    const file = input.files[0];
    const reader = new FileReader();
    reader.onload = e => this.imageSource = String(e.target?.result);
    reader.readAsDataURL(file);
  }

  imageCropped(event: string) {
    this.croppedImage = event;
  }
}
Enter fullscreen mode Exit fullscreen mode

That’s it.
One component. No side effects.


How it compares to popular alternatives

A widely used Angular cropper is ngx-image-cropper, which has a mature API and a large user base.
It’s powerful, but also heavier and more opinionated in behavior.

With ngx-smart-cropper you get:

  • a lean, standalone component
  • full control over layout and styling
  • predictable sizing and behavior
  • smooth touch interaction
  • visuals that don’t need to be hidden or replaced

It’s a better fit when you care about long-term maintainability and UI quality.


Try it out

GitHub: https://github.com/kurti-vdb/ngx-smart-cropper
npm: https://www.npmjs.com/package/ngx-smart-cropper
Live demo: https://ngx-smart-cropper.upsights.be/

If this tool saves you time or solves a frustrating UI problem, a ⭐ on GitHub really helps others find it.


Final thoughts

Libraries should disappear into your app, not fight with your architecture.

That was the goal with ngx-smart-cropper:
a cropper that feels like Angular, behaves like Angular, and looks good doing it.

If cropping images in Angular ever annoyed you more than it should have, give this one a try and let me know what you think.

Top comments (0)