DEV Community

Cover image for Crop and resize images with CSS
Tero Auralinna
Tero Auralinna

Posted on • Originally published at auralinna.blog on

Crop and resize images with CSS

Sometimes you don't have an option to crop images on the server side so you need to do cropping in the browser instead. Here are few examples how to create cropped image thumbnails using CSS only. All the examples are responsive and work for most image aspect ratios. Cropped images are scaled and centered to maximize visible area of image. Notes about browser support and other limitations are marked below.

None of the examples are superior so it's mostly a matter of personal preference which one to use. Though there are a minor variations in a browser support.

All the solutions except SVG requires usage of a transparent placeholder image. It's possible to alter aspect ratio of thumbnail by changing placeholder image size. The examples are built to show images in grid.

Smallest image size available should be used when using CSS cropping because it will affect images loading time.

See the complete crop examples and the code in action at the CodePen.

Image as a background

Pros:

  • Good browser support.
  • Background image properties allows to alter image position nicely.

Cons:

  • Screen reader only image is needed for accessibility (for alt text).
  • Also SEO is addressed with this same image (though have to admin I'm not sure how search engines will treat this hidden image or do they index background images).
  • Visitor can't view or download original image from browser's dialog easily.

HTML

<div class="image-grid">
  <a href="#" class="image-bg" style="background-image:url(https://url.to.image/image.jpg)">
    <img class="image-bg-placeholder" src="https://url.to.image/placeholder.png" alt="" />
    <img class="image-bg-img sr-only" src="https://url.to.image/image.jpg" alt="Cropped image as a background example" />
  </a>
</div>

CSS

.image-grid {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-flex-wrap: wrap;
      -ms-flex-wrap: wrap;
          flex-wrap: wrap;
  margin: 0 auto 35px;
  max-width: 920px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0,0,0,0);
  white-space: nowrap;
  clip-path: inset(50%);
  border: 0;
}

.image-bg {
  background-position: center center;
  background-size: cover;
  -webkit-flex: 0 0 auto;
      -ms-flex: 0 0 auto;
          flex: 0 0 auto;
  margin: 5px;
  width: calc(25% - 10px);
}
.image-bg-placeholder {
  height: 100%;
  visibility: hidden;
  width: 100%;
}

The object-fit property

The object-fit is a similar property than background-size which allows to choose how element should be resized to its container.

Pros:

  • Object-position property allows to alter image position same way as background image.

Cons:

HTML

<div class="image-grid">
  <a href="#" class="image-fit">
    <img class="image-fit-placeholder" src="https://url.to.image/placeholder.png" alt="" />
    <img class="image-fit-img" src="https://url.to.image/image.jpg" alt="Cropped image using object-fit example" />
  </a>
</div>

CSS

.image-grid {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-flex-wrap: wrap;
      -ms-flex-wrap: wrap;
          flex-wrap: wrap;
  margin: 0 auto 35px;
  max-width: 920px;
}

.image-fit {
  -webkit-flex: 0 0 auto;
      -ms-flex: 0 0 auto;
          flex: 0 0 auto;
  margin: 5px;
  position: relative;
  width: calc(25% - 10px);
}
.image-fit-placeholder {
  height: 100%;
  visibility: hidden;
  width: 100%;
}
.image-fit-img {
  bottom: 0;
  height: 100%;
  left: 0;
  object-fit: cover;
  object-position: center;
  position: absolute;
  right: 0;
  top: 0;
  width: 100%;
}

Absolute positioned image

Pros:

  • Good browser support.

Cons:

  • It's not possible to crop and scale vertical and horizontal images perfectly without knowing an image aspect ratio. In my example I have set max-height and max-width so that they work with aspect ratios I have used. But you need to choose if the horizontal or vertical image is displayed correctly. Alternatively you can add a CSS class into image if you check the aspect ratio on server side or with the Javascript. Then you could implement different styles for vertical and horizontal images.

HTML

<div class="image-grid">
  <a href="#" class="image">
    <img class="image-placeholder" src="https://url.to.image/placeholder.png" alt="" />
    <img class="image-img" src="https://url.to.image/image.jpg" alt="Cropped image example" />
  </a>
</div>

CSS

.image-grid {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
  -webkit-flex-wrap: wrap;
      -ms-flex-wrap: wrap;
          flex-wrap: wrap;
  margin: 0 auto 35px;
  max-width: 920px;
}

.image {
  -webkit-flex: 0 0 auto;
      -ms-flex: 0 0 auto;
          flex: 0 0 auto;
  margin: 5px;
  overflow: hidden;
  position: relative;
  width: calc(25% - 10px);
}
.image-placeholder {
  height: 100%;
  visibility: hidden;
  width: 100%;
}
.image-img {
  left: 50%;
  max-height: 150%;
  max-width: 177%;
  position: absolute;
  top: 50%;
  -webkit-transform: translate(-50%, -50%);
      -ms-transform: translate(-50%, -50%);
          transform: translate(-50%, -50%);
}

Image inside the SVG

Using the SVG is a new idea for me. Thanks for Cloud Four: Cropping Image Thumbnails with SVG blog post where I noticed this technique.

I enhanced the example a little bit by making it responsive and added SVG title for accessibility. Title works as an alt text.

Pros:

  • Doesn't need placeholder so the original image is the only image needed.

Cons:

  • Image rendering quality is rough in certain browsers and resolutions.
  • Was the most trickiest one to get displayed nicely in all the browsers.

HTML

<div class="svg-image-grid">
  <a href="#" class="image-svg">
    <svg viewBox="0 0 1 1" role="img">
      <title>Cropped image using SVG example</title>
      <image xlink:href="https://url.to.image/image.jpg" width="100%" height="100%" preserveAspectRatio="xMidYMid slice" />
    </svg>
  </a>
</div>

CSS

.svg-image-grid {
  clear: both;
  margin: 0 auto 35px;
  max-width: 920px;
  overflow: hidden;
  position: relative;
}

.image-svg {
  float: left;
  margin: 5px;
  padding-bottom: calc(25% - 10px);
  position: relative;
  width: calc(25% - 10px);
}
.image-svg svg {
  bottom: 0;
  display: block;
  height: 100%;
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
  width: 100%;
}

It would be interesting to know if you have used any other techniques successfully or have use cases when you can't use certain example mentioned here.


This blog post was originally published on Auralinna.blog

Top comments (3)

Collapse
 
dustinsoftware profile image
masters.🤔

Thanks for the post! I've used both the object-fit: contain and position: absolute approaches in production, and they've worked pretty well. Haven't yet given the SVG approach a shot, on what devices did you get a poor render result?

Collapse
 
teroauralinna profile image
Tero Auralinna

Hi, thanks for the comment. Poor rendering is visible at least on Firefox (Win/Mac). Also in IE11. Issue is most visible on vertical thin lines. So most of the images are fine. And I noticed it only on my external display. Not on my MacBook screen. So I guess it depends on multiple factors :)

Collapse
 
valerauko profile image
Vale

I replicated Twitter's layout of images (1 big and 3 small etc) with CSS grid layout. It took a bit of playing around with flexbox in the cells and auto-sizing, but the result seems reliable in proper browsers.