Monsoon v0.2.0
Made by Alexandre Kohler Star

Media and files

Image cropper

Move and resize the crop box with its handles or the keyboard, pick an aspect (free, 1:1, 4:3, 16:9, 3:4, circle), zoom with the slider, wheel or a pinch, rotate, flip, and export to a canvas, Blob, data URL or File. Drop or paste another image to crop it. It needs monsoon.js. Without it the image is shown as is.

Media and files11 classesNeeds monsoon.jsLight and dark

Needs monsoon.js. The styles work on their own, and the behavior comes from the optional interactive layer: add <script src="https://cdn.jsdelivr.net/npm/monsooncss/dist/monsoon.js" defer></script> or import 'monsooncss/js'. See the interactive layer.

Example

Full

JavaScript API

Attribute

data-m-cropper on a .cropper that contains an <img>

Options

OptionDescription
data-m-cropper-aspectStarting aspect: free, circle, 1:1, 4:3, 16:9, 3:4 or any w:h or number.
data-m-cropper-aspectsComma list of the presets in the toolbar, or none.
data-m-cropper-previewSelector of preview elements, the nearest match is used; each gets the cropper-preview class.
data-m-cropper-max-zoomLargest zoom, 8 by default.
data-m-cropper-maxCaps the long side of exports in pixels.
data-m-cropper-toolbarfalse hides the toolbar.

Methods

MethodDescription
Monsoon.cropper(el).toBlob(type, quality, options)Promise of a Blob. options: { width, height, max, circle, background }.
Monsoon.cropper(el).toFile(name, type, quality, options)Promise of a File, ready for FormData.
Monsoon.cropper(el).toDataURL(type, quality, options)A data URL string.
Monsoon.cropper(el).toCanvas(options)A canvas with the crop at source resolution.
Monsoon.cropper(el).getData(){ x, y, width, height } in source pixels of the turned image, plus rotate, flipX, flipY and zoom.
Monsoon.cropper(el).setAspect(name)Changes the aspect, keeping the centre and area.
Monsoon.cropper(el).zoom(value)Zoom from 1 (whole image) to max zoom.
Monsoon.cropper(el).rotate(turns)Turns by 90 degree steps.
Monsoon.cropper(el).flip(axis)Flips on x or y.
Monsoon.cropper(el).setBox({ x, y, w, h })Places the crop box in stage pixels.
Monsoon.cropper(el).load(srcOrFile)Loads another image, returns a Promise.
Monsoon.cropper(el).reset()Back to the starting state.

Events

EventDescription
monsoon:cropper-readyThe image is loaded, detail is the crop data.
monsoon:cropThe crop changed (once per frame while dragging), detail is the crop data.

Keyboard

Focus the crop box: arrows move it, Shift and arrows resize it, Ctrl or Alt moves 10 pixels, plus and minus zoom.

Classes

11 classes. Click a name to copy it. Utilities on the same element always win over component defaults, so any of them can be adjusted with plain utility classes.

ClassTypeWhat it does
Base Base class of the image cropper. On a <div> in the example. Sets grid display, grid tracks, gap, width, block display and corner radius, and --tone, --tone-fg and --cropper-h.
CSS
.cropper[data-circle] .cropper-box {
  border-radius: 50%;
}

.cropper[data-drag=pan] .cropper-stage {
  cursor: grabbing;
}
Modifier Modifier, combined with the cropper class. Not used in the example above. Sets height, overflow, corner radius, background, shadow and grab cursor.
CSS
.cropper-stage {
  position: relative;
  height: var(--cropper-h);
  overflow: hidden;
  border-radius: var(--m-radius-xl);
  background-color: var(--surface-2);
  background-image: conic-gradient(var(--surface-3) 25%, transparent 0 50%, var(--surface-3) 0 75%, transparent 0);
  background-size: 1rem 1rem;
  box-shadow: inset 0 0 0 var(--m-border-width) var(--border);
  cursor: grab;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
}

.cropper[data-drag=pan] .cropper-stage {
  cursor: grabbing;
}
Modifier Modifier, combined with the cropper class. Not used in the example above. Sets absolute position, offsets and width.
CSS
.cropper-image {
  position: absolute;
  top: 0;
  left: 0;
  max-width: none;
  transform-origin: 0 0;
  pointer-events: none;
}
Modifier Modifier, combined with the cropper class. Not used in the example above. Sets absolute position, offsets, shadow, border, move cursor and opacity.
CSS
.cropper[data-active] .cropper-grid,
.cropper-box:focus-visible .cropper-grid {
  opacity: 1;
}

.cropper-box:focus-visible {
  outline: var(--m-ring-width) solid var(--ring);
  outline-offset: 0;
}
Modifier Modifier, combined with the cropper class. Not used in the example above. Sets absolute position, offsets, corner radius, background, opacity and transition.
CSS
@media (prefers-reduced-motion: reduce) {
  .dropzone-area,
  .dropzone-glyph,
  .dropzone-item,
  .dropzone-errors,
  .dropzone-progress,
  .dropzone-progress::before,
  .cropper-grid,
  .cropper-handle::after,
  .avatar-upload-badge,
  .viewer,
  .viewer-image,
  .viewer-thumb,
  .gallery-item,
  .gallery-item img,
  .gallery-check,
  .gallery-check > input,
  .gallery-check > input::before,
  .compare-knob,
  .signature-hint,
  .signature-swatch {
    transition: none;
    animation: none;
  }
}

.cropper-grid {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(to right, transparent calc(100% / 3 - .5px), oklch(1 0 0 / .55) 0 calc(100% / 3 + .5px), transparent 0 calc(200% / 3 - .5px), oklch(1 0 0 / .55) 0 calc(200% / 3 + .5px), transparent 0),
    linear-gradient(to bottom, transparent calc(100% / 3 - .5px), oklch(1 0 0 / .55) 0 calc(100% / 3 + .5px), transparent 0 calc(200% / 3 - .5px), oklch(1 0 0 / .55) 0 calc(200% / 3 + .5px), transparent 0);
  opacity: 0.35;
  pointer-events: none;
  transition: opacity var(--m-duration) var(--m-ease);
}
Modifier Modifier, combined with the cropper class. Not used in the example above. Sets absolute position, stacking order, grid display, alignment, width and height.
CSS
.cropper-handle:hover::after {
  scale: 1.25;
}

.cropper-handle[data-handle=n] {
  top: 0;
  left: 50%;
  cursor: ns-resize;
}
Modifier Modifier, combined with the cropper class. Not used in the example above. Sets flex display, alignment, gap, width and overflow.
CSS
.cropper-toolbar > .segmented {
  max-width: 100%;
  overflow-x: auto;
  scrollbar-width: none;
}

.cropper-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 0.75rem;
}
Modifier Modifier, combined with the cropper class. Not used in the example above. Sets flex display, alignment, gap and width.
CSS
.cropper-zoom {
  display: flex;
  flex: 1 1 8rem;
  align-items: center;
  gap: 0.25rem;
  min-width: 7.5rem;
}
Modifier Modifier, combined with the cropper class. Not used in the example above. Sets flex display and gap.
CSS
.cropper-actions {
  display: flex;
  gap: 0.125rem;
}
Modifier Modifier, combined with the cropper class. Not used in the example above. Sets overflow, corner radius, background, shadow, absolute position and offsets.
CSS
.cropper-preview-circle, .cropper-preview[data-circle] {
  border-radius: 50%;
}

.cropper-preview > img {
  position: absolute;
  top: 0;
  left: 0;
  max-width: none;
  transform-origin: 0 0;
}
Modifier Modifier, combined with the cropper class. Not used in the example above. Sets corner radius.
CSS
.cropper-preview-circle, .cropper-preview[data-circle] {
  border-radius: 50%;
}

Usage

The styles ship inside the same stylesheet as the utilities, and the behavior comes from the optional monsoon.js script, which enhances any element with a matching data-m attribute, including markup added later.

index.html
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/monsooncss">
<script src="https://cdn.jsdelivr.net/npm/monsooncss/dist/monsoon.js" defer></script>

<!-- Image cropper: start from the base class, then add modifiers -->
<div class="flex flex-wrap items-start gap-4"><div class="cropper min-w-0 flex-1 basis-64" data-m-cropper data-m-cropper-aspect="4:3" data-m-cropper-preview="[data-crop-preview]"><img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='1200'%20height='800'%20viewBox='0%200%201200%20800'%3E%3Cdefs%3E%3ClinearGradient%20id='s'%20x2='0'%20y2='1'%3E%3Cstop%20offset='0'%20stop-color='%23fdba74'/%3E%3Cstop%20offset='1'%20stop-color='%23f472b6'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect%20width='1200'%20height='800'%20fill='url(%23s)'/%3E%3Ccircle%20cx='840'%20cy='272'%20r='88'%20fill='%23fff7d6'/%3E%3Cpath%20d='M0%20496L240%20336L456%20464L720%20288L1200%20528V800H0Z'%20fill='%237c3aed'/%3E%3Cpath%20d='M0%20592L336%20448L624%20576L936%20480L1200%20608V800H0Z'%20fill='%233b0764'/%3E%3Crect%20y='672'%20width='1200'%20height='128'%20fill='%231e1b4b'%20opacity='.85'/%3E%3C/svg%3E" alt="Violet ridges at dusk"></div><div class="grid w-32 gap-2"><div data-crop-preview></div><span class="text-xs text-muted-foreground">Live preview</span></div></div>

Theme it with --seed on any ancestor, for example style="--seed: #0d9488", and force a scheme with class="dark" or class="light" on a wrapper.

Accessibility

  • Give meaningful images an alt text and decorative ones alt="". Initials avatars should expose the full name to screen readers.
  • Every interactive part shows a visible focus ring with :focus-visible, and tone colors pair with -foreground tokens that keep text at 4.5:1 or better in light and dark mode.

No recent searches

Try , , or .

Recent

Loading the search index

No results for ""

Check the spelling, or search a class name such as px-4.