424

I want to show an image from an URL with a certain width and height even if it has a different size ratio. So I want to resize (maintaining the ratio) and then cut the image to the size I want.

I can resize with html img property and I can cut with background-image.
How can I do both?

Example:

This image:

enter image description here


Has the size 800x600 pixels and I want to show like an image of 200x100 pixels


With img I can resize the image 200x150px:

<img 
    style="width: 200px; height: 150px;" 
    src="https://i.stack.imgur.com/wPh0S.jpg">


That gives me this:

<img style="width: 200px; height: 150px;" src="https://i.stack.imgur.com/wPh0S.jpg">


And with background-image I can cut the image 200x100 pixels.

<div 
    style="background-image:
           url('https://i.stack.imgur.com/wPh0S.jpg'); 
    width:200px; 
    height:100px; 
    background-position:center;">&nbsp;</div>

Gives me:

    <div style="background-image:url('https://i.stack.imgur.com/wPh0S.jpg'); width:200px; height:100px; background-position:center;">&nbsp;</div>


How can I do both?
Resize the image and then cut it the size I want?

MauriceNino
  • 6,214
  • 1
  • 23
  • 60
InfoStatus
  • 6,983
  • 9
  • 41
  • 53

21 Answers21

547

You could use a combination of both methods eg.

    .crop {
        width: 200px;
        height: 150px;
        overflow: hidden;
    }

    .crop img {
        width: 400px;
        height: 300px;
        margin: -75px 0 0 -100px;
    }
    <div class="crop">
        <img src="https://i.stack.imgur.com/wPh0S.jpg" alt="Donald Duck">
    </div>

You can use negative margin to move the image around within the <div/>.

LWC
  • 1,084
  • 1
  • 10
  • 28
roborourke
  • 12,147
  • 4
  • 26
  • 37
  • 9
    Note that if you set position:relative on the contained image, you'll need to set position:relative on the containing div. If you don't, I've found that IE won't actually clip the image. – Frank Schwieterman Jun 26 '09 at 22:56
  • also remove height from .crop img class – Waqar Alamgir May 25 '11 at 16:32
  • @waqar-alamgir It wouldn't work if you removed the height declaration – roborourke May 26 '11 at 15:43
  • 6
    Also note that when using css to crop an image, the user still has to download the image. It might be better to use php and GD or another image editing library to resize and crop the image before sending it to the user. It all depends on what you want, loading the server or the users bandwidth. – J-Rou Aug 19 '11 at 16:35
  • 19
    Just a note for others: .crop height and width define where to slice the bottom-most and right-most part of the image. .crop img height and width will scale the image. .crop img margin will pan the image – Frederik Apr 25 '12 at 13:59
  • @sanchothefat Suppose we don't know the image size. We need to specify the margin using Javascript. Right? So that can cause a flickering effect. Can you think of any other solution? – Jeevan Oct 29 '12 at 11:42
  • @Jeevan hide the image until your JS runs using visibility:hidden; – colllin Nov 26 '12 at 20:11
  • @collindo Yes. it will work if its like a single time render. Suppose you are rendering something in a SERP, which is search as you type. And you are using this to show images the search results. So each time you make visibility hidden the images will flicker. – Jeevan Nov 27 '12 at 05:29
  • @Jeevan it will work for any scenario if implemented well. For example, render the image with a special class `js-hide-until-loaded` then remove that class when the image's onload event fires. `onload="doSomething(this); $(this).removeClass('js-hide-until-loaded')"` – colllin Nov 27 '12 at 23:22
  • @collindo My concern was initially making it visibility:hidden and then later making it visible onload. Since we are updating a div say every second it will cause a slight flicker. You can't makeout when a text flickers in a SERP but for images its different. – Jeevan Nov 28 '12 at 08:02
  • Is there any way to make the cropped image responsive? http://coding.smashingmagazine.com/2011/01/12/guidelines-for-responsive-web-design/ – skibulk Apr 07 '14 at 13:36
  • @skibulk you'd just have to use percentage widths and perhaps a max-width on the image. The same approach should still apply – roborourke Apr 07 '14 at 14:05
154

With CSS3 it's possible to change the size of a background-image with background-size, fulfilling both goals at once.

There are a bunch of examples on css3.info.

Implemented based on your example, using donald_duck_4.jpg. In this case, background-size: cover; is just what you want - it fits the background-image to cover the entire area of the containing <div> and clips the excess (depending on the ratio).

.with-bg-size {
  background-image: url('https://i.stack.imgur.com/wPh0S.jpg');
  width: 200px;
  height: 100px;
  background-position: center;
  /* Make the background image cover the area of the <div>, and clip the excess */
  background-size: cover;
}
<div class="with-bg-size">Donald Duck!</div>

Joel Purra
  • 24,294
  • 8
  • 60
  • 60
  • 1
    Great solution, but one caveat is that it isn't compatible with IE <9 (If that matters to anyone anymore). Also, I wanted to mention, if you replace cover with contain for background-size, it will scale, but not crop the image. – devnate Nov 21 '13 at 18:42
  • 5
    For `` tags, look at [`object-fit: cover`](https://developer.mozilla.org/en/docs/Web/CSS/object-fit) and related values from the [CSS Image Values and Replaced Content Module Level 3 specification](https://drafts.csswg.org/css-images-3/#the-object-fit). – Joel Purra Jul 26 '16 at 07:21
134

Did you try to use this?

.centered-and-cropped { object-fit: cover }

I needed to resize image, center (both vertically and horizontally) and than crop it.

I was happy to find, that it could be done in a single css-line. Check the example here: http://codepen.io/chrisnager/pen/azWWgr/?editors=110


Here is the CSS and HTMLcode from that example:

.centered-and-cropped { object-fit: cover }
<h1>original</h1>
<img height="200" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/3174/bear.jpg" alt="Bear">
    
<h1>object-fit: cover</h1>
<img class="centered-and-cropped" width="200" height="200" 
style="border-radius:50%" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/3174/bear.jpg" alt="Bear">
Roman Cherepanov
  • 1,639
  • 2
  • 24
  • 44
Anatolii Stepaniuk
  • 2,585
  • 1
  • 18
  • 24
  • 2
    Thanks, I think this is the easiest and most universal way to go - but it doesn't seem to work with IE :/ Find the docs here: https://developer.mozilla.org/de/docs/Web/CSS/object-fit – mozzbozz Aug 04 '15 at 11:57
  • 2
    CSS3 object-fit is not supported by IE11 or EDGE(14) http://caniuse.com/#feat=object-fit – eye-wonder Nov 01 '16 at 09:10
  • 1
    @eye-wonder it is supported in Edge 16, coming out soon. If its non critical and used sparingly, it could be used today – Ray Foss Jul 17 '17 at 19:07
  • In CSS3, we can try either way img+object-fit or div+background-image. So far in my experience background-image can be used to fit more conditions. – Eric Feb 02 '18 at 07:22
  • 1
    As of now this is also supported by Edge (don't know since when though). – Gerald Schneider Jul 30 '18 at 13:02
  • There is object-fit polyfill for IE9+ https://github.com/constancecchen/object-fit-polyfill/blob/master/README.md – Vincente Jan 08 '20 at 12:50
22
.imgContainer {
  overflow: hidden;
  width: 200px;
  height: 100px;
}
.imgContainer img {
  width: 200px;
  height: 120px;
}
<div class="imgContainer">
  <img src="imageSrc" />
</div>

The containing div with essentially crop the image by hiding the overflow.

Igor Ivancha
  • 3,413
  • 4
  • 30
  • 39
Kelly Anderson
  • 366
  • 1
  • 3
14
img {
  position: absolute;
  clip: rect(0px, 140px, 140px, 0px);
}
<img src="w3css.gif" width="100" height="140" />
Igor Ivancha
  • 3,413
  • 4
  • 30
  • 39
Rohit Chaudhary
  • 175
  • 1
  • 2
  • 14
10

A small addition to the previous answers that includes object-fit: cover:

object-position

You can alter the alignment of the replaced element's content object within the element's box using the object-position property.

.trimmed-cover {
  object-fit: cover;
  width: 100%;
  height: 177px;
  object-position: center 40%;
}
<img class="trimmed-cover" src="https://i.stack.imgur.com/wPh0S.jpg">

result.gif

Mahmoud
  • 9,729
  • 1
  • 36
  • 47
9

Thanks sanchothefat.

I have an improvement to your answer. As crop is very tailored for every image, this definitions should be at the HTML instead of CSS.

<div style="overflow:hidden;">
   <img src="img.jpg" alt="" style="margin:-30% 0px -10% 0px;" />
</div>
Kirby
  • 15,127
  • 10
  • 89
  • 104
Pedro Reis
  • 1,587
  • 1
  • 19
  • 19
8

object-fit may help you, if you're playing with <img> tag

The below code will crop your image for you. You can play around with object-fit

img {
  object-fit: cover;
  width: 300px;
  height: 337px;
}
Hidayt Rahman
  • 2,490
  • 26
  • 32
6
img {
    position: absolute;
    clip: rect(0px,60px,200px,0px);
} 
151291
  • 3,308
  • 7
  • 48
  • 81
6

Try using the clip-path property:

The clip-path property lets you clip an element to a basic shape or to an SVG source.

Note: The clip-path property will replace the deprecated clip property.

img {
  width: 150px;
  clip-path: inset(30px 35px);
}
<img src="https://i.stack.imgur.com/wPh0S.jpg">

More examples here.

Emeric
  • 6,315
  • 2
  • 41
  • 54
5

Live Example: https://jsfiddle.net/de4Lt57z/

HTML:

<div class="crop">
  <img src="example.jpg" alt="..." />
</div>

CSS:

    .crop img{
      width:400px;
      height:300px;
      position: absolute;
      clip: rect(0px,200px, 150px, 0px);
      }

Explanation: Here image is resized by width and height value of the image. And crop is done by clip property.

For details about clip property follow: http://tympanus.net/codrops/2013/01/16/understanding-the-css-clip-property/

Md Rafee
  • 5,070
  • 3
  • 23
  • 32
4

In the crop class, place the image size that you want to appear:

.crop {
    width: 282px;
    height: 282px;
    overflow: hidden;
}
.crop span.img {
    background-position: center;
    background-size: cover;
    height: 282px;
    display: block;
}

The html will look like:

<div class="crop">
    <span class="img" style="background-image:url('http://url.to.image/image.jpg');"></span>
</div>
Deivide
  • 529
  • 8
  • 14
3
<p class="crop"><a href="http://templatica.com" title="Css Templates">
    <img src="img.jpg" alt="css template" /></a></p> 

.crop {
    float: left;
    margin: .5em 10px .5em 0;
    overflow: hidden; /* this is important */
    position: relative; /* this is important too */
    border: 1px solid #ccc;
    width: 150px;
    height: 90px;
}
.crop img {
    position: absolute;
    top: -20px;
    left: -55px;
}
Linus Caldwell
  • 10,908
  • 12
  • 46
  • 58
Sergey Chechaev
  • 562
  • 7
  • 22
2

There are services like Filestack that will do this for you.

They take your image url and allow you to resize it using url parameters. It is pretty easy.

Your image would look like this after resizing to 200x100 but keeping the aspect ratio

The whole url looks like this

https://process.filestackapi.com/AhTgLagciQByzXpFGRI0Az/resize=width:200/crop=d:[0,25,200,100]/https://i.stack.imgur.com/wPh0S.jpg

but the important part is just

resize=width:200/crop=d:[0,25,200,100]

enter image description here

ferrantim
  • 504
  • 3
  • 3
  • nice plug maybe - but equally - an awesome service (no, I'm not paid to say this ;-) ) - I literally have just signed up and it's pretty cool – Jonathan Lyon Apr 11 '17 at 06:48
1
<div class="crop">
    <img src="image.jpg"/>
</div>
.crop {
  width: 200px;
  height: 150px;
  overflow: hidden;
}
.crop img {
  width: 100%;
  /*Here you can use margins for accurate positioning of cropped image*/
}
Igor Ivancha
  • 3,413
  • 4
  • 30
  • 39
Krone
  • 78
  • 11
1

You can put the img tag in a div tag and do both, but I would recommend against scaling images in the browser. It does a lousy job most of the time because browsers have very simplistic scaling algorithms. Better to do your scaling in Photoshop or ImageMagick first, then serve it up to the client nice and pretty.

Dave Markle
  • 95,573
  • 20
  • 147
  • 170
1

What I've done is to create a server side script that will resize and crop a picture on the server end so it'll send less data across the interweb.

It's fairly trivial, but if anyone is interested, I can dig up and post the code (asp.net)

Rob
  • 2,080
  • 4
  • 28
  • 48
  • CGI is probably the most portable method (and bandwidth-efficient), unless the OP intends to allow the user to perform their own resizing and cropping via Javascript. – strager Jan 29 '09 at 20:48
0

If you are using Bootstrap, try using { background-size: cover; } for the <div> maybe give the div a class say <div class="example" style=url('../your_image.jpeg');> so it becomes div.example{ background-size: cover}

0

I needed to do this recently. I wanted to make a thumbnail-link to a NOAA graph. Since their graph could change at any time, I wanted my thumbnail to change with it. But there's a problem with their graph: it has a huge white border at the top, so if you just scale it to make the thumbnail you end up with extraneous whitespace in the document.

Here's how I solved it:

http://sealevel.info/example_css_scale_and_crop.html

First I needed to do a little bit of arithmetic. The original image from NOAA is 960 × 720 pixels, but the top seventy pixels are a superfluous white border area. I needed a 348 × 172 thumbnail, without the extra border area at the top. That means the desired part of the original image is 720 - 70 = 650 pixels high. I needed to scale that down to 172 pixels, i.e., 172 / 650 = 26.5%. That meant 26.5% of 70 = 19 rows of pixels needed to be deleted from the top of the scaled image.

So…

  1. Set the height = 172 + 19 = 191 pixels:

    height=191

  2. Set the bottom margin to -19 pixels (shortening the image to 172 pixels high):

    margin-bottom:-19px

  3. Set the top position to -19 pixels (shifting the image up, so that the top 19 pixel rows overflow & are hidden instead of the bottom ones):

    top:-19px

The resulting HTML looks like this:

<a href="…" style="display:inline-block;overflow:hidden">
<img width=348 height=191 alt=""
style="border:0;position:relative;margin-bottom:-19px;top:-19px"
src="…"></a>

As you can see, I chose to style the containing <a> tag, but you could style a <div>, instead.

One artifact of this approach is that if you show the borders, the top border will be missing. Since I use border=0 anyhow, that wasn't an issue for me.

Dave Burton
  • 2,960
  • 29
  • 19
0

You can use Kodem's Image Resize Service. You can resize any image with just a http call. Can be used casually in the browser or used in your production app.

  • Upload the image somewhere you prefer (S3, imgur etc.)
  • Plug it into your dedicated API url (from our dashboard)
Thellimist
  • 3,757
  • 5
  • 31
  • 49
0

You can also use a tool called Croppie that can crop images...

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<link href="https://foliotek.github.io/Croppie/croppie.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"> </script>
<script src="https://foliotek.github.io/Croppie/croppie.js"> </script>
<script src="https://foliotek.github.io/Croppie/bower_components/exif-js/exif.js"> </script>

<style>
    #page {
        background: #ffffff;
        padding: 20px;
        margin: 20px;
    }

    #demo-basic {
        width: 600px;
        height: 600px;
    }
</style>
</head>
<body>
<h1>Crop Image Demo</h1>
<input id="upload" type="file" />
<br />
<div id="page">
<div id="demo-basic"></div>
</div>

<input id="upload-result" type="button" value="Crop Image"/>
<br />
<img id="cropped-result" src=""/>

<script>
    var $uploadCrop;       

    $("#upload").on("change", function () { readFile(this); show(); });

    $("#upload-result").on("click", function (ev) {
        $uploadCrop.croppie("result", {
            type: "canvas",
            size: "viewport"
        }).then(function (resp) {
            $("#cropped-result").attr("src", resp);
        });
    });

    function show() {
        $uploadCrop = $("#demo-basic").croppie({
            viewport: { width: 100, height: 100 },
            boundary: { width: 300, height: 300 },
            enableResize: true,
            enableOrientation: true,
            mouseWheelZoom: 'ctrl',
            enableExif: true
        });
    }

    function readFile(input) {
        if (input.files && input.files[0]) {
            var reader = new FileReader();
        
            reader.onload = function (e) {
                $("#demo-basic").addClass("ready");
                $uploadCrop.croppie("bind", {
                    url: e.target.result
                }).then(function () {
                    console.log("jQuery bind complete");
                });
            
            }
        
            reader.readAsDataURL(input.files[0]);
        }
        else {
            alert("Sorry - you're browser doesn't support the FileReader API");
        }
    }
</script>
</body>
</html>
MrAni
  • 23
  • 6