• Works in Safari 3+, Firefox 3+, Chrome 3+, IE 6-11 and Opera 9+
  • Requires mootools 1.23+ with Drag.Move and (for example) PHP to crop the image
  • (Note: The included local demo has some issues with IE 11, the online version works)


Download at Mootools Forge »

Comments? Problems? Feedback? Leave a comment »


  • If you use the default settings, the HTML-code found in /Demo/ can simply be used (except filename and sizes of course)
  • Initialize the CwCrop-Object as seen below, adding options you’d like to change
  • Here a form is prepared to capture the resulting rectangle dimensions (x,y and w,h)
  • The method ch.doCrop() triggers the onCrop event, which writes the dimensions to the form fields and submits the form
Javascript Code
var ch = new CwCrop({
    onCrop: function(values) {
        document.forms["crop"].elements["crop[x]"].value = values.x;
        document.forms["crop"].elements["crop[y]"].value = values.y;
        document.forms["crop"].elements["crop[w]"].value = values.w;
        document.forms["crop"].elements["crop[h]"].value = values.h;
    minsize: {x: 100, y: 100},
    maxratio: {x: 2, y: 1},
    fixedratio: false
Options (with their default values)
  • minsize: {x: 60, y: 60} – the minimal size of the resulting image (user can not make it smaller)
  • maxsize: {x: 200, y: 200} – the maximal size of the resulting image (user can not make it bigger)
  • initialposition: {x: 10, y: 10} – the initial position of the crop area (from top left)
  • fixedratio: false – set to a number if the rectangle should have a fixed ratio (maxratio is ignored then)
  • maxratio: {x: 2, y: 2} – the maximum ratio for x and y
  • originalsize: {x: 1, y: 1} – the size of the original image, optional (see below)
  • initialmax: false – extend the selection rectangle to the maximum size initially
  • classactive: “active” – name of the class which is applied to the cropframe if the user selects it
  • cropframe: “cropframe” – id of the outer div
  • imgframe: “imglayer” – id of the layer div
  • cropdims: “cropdims” – id of the div which shows the current position/dimension (can be empty)
  • cropbtn: “cropbtn” – id of a div (or something else), which trigger the cropping
  • draghandle: “draghandle” – id of the div of the drag-handle
  • resizehandle: “resizeHandleXY” – id of the div of the resize-handle
  • onCrop – Triggered if the user clicks “crop” or if doCrop() is called.
    The result is this object: {‘x’: x-position, ‘y’: y-position, ‘w’: width, ‘h’: height}
Using two images

It is possible to use one image (a smaller one usually) for the crop area and another one (the original) which is cropped. This is useful is you for example crop big photos which are too large to handle in a browser.

Therefore set originalsize to the dimensions of the original image, the rest is calculated automatically. The minsize and maxsize parameters are used in respect to the original image then.

Note that there are of course scaling and rounding differences of some pixels if the original image is much larger than the preview image.


This is the structure needed for the crop-tool. The image is referenced two times as background image, the “imglayer” needs the image dimensions.

“cropdims” is a layer showing the current selected dimensions, you can remove it if it’s not needed.

Same goes for “cropbtn”, remove the line (and add a button somewhere, which triggers “ch.doCrop()”).

<div id="imgouter">
    <div id="cropframe" style="background-image: url('image.jpg')">
        <div id="draghandle"></div>
        <div id="resizeHandleXY" class="resizeHandle"></div>
        <div id="cropinfo" rel="Click to crop">
            <div title="Click to crop" id="cropbtn"></div>
            <div id="cropdims"></div>
    <div id="imglayer" style="width: 200px; height: 192px; background-image: url(image.jpg')">

You can also use an “external” button, which triggers the crop-event:

<button onclick="ch.doCrop()">Crop</button>
CSS Code

The default CSS code, modify as needed.

#imgouter {
   position: relative; border: none; margin-left: 10px;
   z-index: 200;

#imglayer {
   padding: 1px;
   background-position: center center;
   background-color: transparent; background-repeat: no-repeat; opacity: 0.5; cursor: default;
   filter:alpha(opacity=50); /* IE 6-7 Trash */
   -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; /* IE8 Trash */
   z-index: 300; 

#cropframe {
   position: absolute; width: 40px; height: 40px; left: 0px; top: 0px; padding: 0px; border: 1px dashed #333; background-repeat: no-repeat;
   -border-image: url('ants.gif') 1 repeat repeat;
   -webkit-border-image: url('ants.gif') 1 repeat repeat;
   -moz-border-image: url('ants.gif') 1 repeat repeat;
   z-index: 999;     
} {
   border: 1px dashed #fff;

#cropinfo {
   background-color: #ccc; opacity: 0.4; top: 0px; left: 0px; height: 32px; position: absolute;
   filter:alpha(opacity=40); /* IE 6-7 Trash */
   -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=40)"; /* IE8 Trash */   
   z-index: 600;

#cropdims {
   color: #000; padding: 6px 5px; margin-left: 32px; font-size: 13px;
   z-index: 500;

#cropbtn {
   background-image:url('crop.gif'); background-repeat: no-repeat;
   position: absolute; left: 0px; height: 32px; width: 32px; cursor: pointer !important;
   z-index: 800;

#cropbtn:hover {
   background-color: black;

#draghandle {
   background-color: transparent; top: 0; left: 0; width: 100%; height: 100%; margin: 0px; position: absolute; cursor: move;
   z-index: 90;

.resizeHandle {
   z-index: 40; opacity: 0.9;
   filter:alpha(opacity=90); /* IE 6-7 Trash */
   -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=90)"; /* IE8 Trash */
   background-color: #666;
   position: absolute; margin: 0px; border: 1px solid #fff; height: 8px; width: 8px;     

#resizeHandleXY {
   left: 100%; top: 100%;    
   cursor: se-resize;