
Crop and resize images with CSS
Published on January 28, 2018. Edited on July 5, 2020.
Sometimes you don't have an option to crop images on the server-side so you need to do the cropping in the browser instead. Here are a few examples of 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 the visible area of the 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 minor variations in browser support.
All the solutions except SVG require the usage of a transparent placeholder image. It's possible to alter the aspect ratio of the thumbnail by changing the placeholder image size. The examples are built to show images in the grid.
The smallest image size available should be used when using CSS cropping because it will affect image loading time.
See the complete crop examples and the code in action at the CodePen.
Embedded content: https://codepen.io/teroauralinna/pen/goXJQL
Image as a background
Pros:
- Good browser support.
- Background image properties allow us to alter the 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 admit I'm not sure how search engines will treat this hidden image or do they index background images).
- Visitors can't view or download original images from the 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>
Styles
.image-grid {
display: flex;
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;
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:
- Internet Explorer doesn't support
object-fit
norobject-position
(image will be shown distorted). Polyfills are available: object-fit-images, objectFitPolyfill. - Also iOS Safari has limited support for
object-fit
andobject-position
.
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>
Styles
.image-grid {
display: flex;
flex-wrap: wrap;
margin: 0 auto 35px;
max-width: 920px;
}
.image-fit {
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
andmax-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 the image if you check the aspect ratio on the 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 using absolute positioning example" />
</a>
</div>
Styles
.image-grid {
display: flex;
flex-wrap: wrap;
margin: 0 auto 35px;
max-width: 920px;
}
.image {
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%;
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>
Styles
.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);
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 examples mentioned here.
Latest blog posts
October 24, 2019
How to fetch your public photos from Instagram without the API
June 12, 2019
CodePen embeds with Contentful and Angular
March 26, 2019
Global HTTP request and response handling with the Axios interceptor
December 2, 2018
Setting up webpack 4 for a project
November 10, 2018
How to create Material Design like form text fields with floating label and animated underline bar
May 2, 2018
How to build a complete form with Vue.js
April 4, 2018
How to transfer the Angular server-side state to the client-side
March 28, 2018
My web developer career story
Latest CodePens
July 9, 2019
Switch between the dark and light mode via CSS custom properties
June 12, 2019
Javascript URL handling
June 9, 2019
Material Design like form input text fields with CSS only
March 27, 2019
Global HTTP request and response handling with the Axios interceptors
March 23, 2019
Navigation wizard example with equal width steps and flexible width of last step
March 23, 2019
Javascript event delegation example
December 9, 2018
Responsive and animated D3.js bar chart with positive and negative values (TypeScript)
November 11, 2018