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.
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
<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>JavaScript API
Attribute
data-m-cropper on a .cropper that contains an <img>
Options
| Option | Description |
|---|---|
data-m-cropper-aspect | Starting aspect: free, circle, 1:1, 4:3, 16:9, 3:4 or any w:h or number. |
data-m-cropper-aspects | Comma list of the presets in the toolbar, or none. |
data-m-cropper-preview | Selector of preview elements, the nearest match is used; each gets the cropper-preview class. |
data-m-cropper-max-zoom | Largest zoom, 8 by default. |
data-m-cropper-max | Caps the long side of exports in pixels. |
data-m-cropper-toolbar | false hides the toolbar. |
Methods
| Method | Description |
|---|---|
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
| Event | Description |
|---|---|
monsoon:cropper-ready | The image is loaded, detail is the crop data. |
monsoon:crop | The 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.
| Class | Type | What 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 |
|
| Modifier | Modifier, combined with the cropper class. Not used in the example above. Sets height, overflow, corner radius, background, shadow and grab cursor.CSS |
|
| Modifier | Modifier, combined with the cropper class. Not used in the example above. Sets absolute position, offsets and width.CSS |
|
| Modifier | Modifier, combined with the cropper class. Not used in the example above. Sets absolute position, offsets, shadow, border, move cursor and opacity.CSS |
|
| Modifier | Modifier, combined with the cropper class. Not used in the example above. Sets absolute position, offsets, corner radius, background, opacity and transition.CSS |
|
| 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 |
|
| Modifier | Modifier, combined with the cropper class. Not used in the example above. Sets flex display, alignment, gap, width and overflow.CSS |
|
| Modifier | Modifier, combined with the cropper class. Not used in the example above. Sets flex display, alignment, gap and width.CSS |
|
| Modifier | Modifier, combined with the cropper class. Not used in the example above. Sets flex display and gap.CSS |
|
| Modifier | Modifier, combined with the cropper class. Not used in the example above. Sets overflow, corner radius, background, shadow, absolute position and offsets.CSS |
|
| Modifier | Modifier, combined with the cropper class. Not used in the example above. Sets corner radius.CSS |
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.
<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
alttext and decorative onesalt="". 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-foregroundtokens that keep text at 4.5:1 or better in light and dark mode.