Skip to main content

Cropping Image Thumbnails with SVG

By Tyler Sticka

Published on August 18th, 2016

Topics

Our friend Aaron Parecki recently blogged about a technique he used for centering and cropping image thumbnails using CSS. It’s a clever technique used by WordPress (and many others), but it requires a containing element with explicit dimensions, making it less than ideal for responsive design.

Using SVG, we can make a cropped image that still acts like an image. No CSS required, works in IE9 and up:

<svg viewBox="0 0 1 1" width="100" height="100">
  <image xlink:href="path/to/image.jpg" 
    width="100%" height="100%" 
    preserveAspectRatio="xMidYMid slice"/>
</svg>
Code language: HTML, XML (xml)

Let’s break down how this works:

  1. The last two values in the viewBox attribute define our desired aspect ratio, in this case a square (1:1).
  2. The first width and height and attributes tell the browser the default dimensions of our cropped image. We can make these any number divisible by our ratio, and we can override them in CSS just like <img> elements.
  3. The <image> element’s xlink:href attribute points to the source image (just like <img src="…">). It can be any size or aspect ratio.
  4. The second width and height attributes force the image to fill the entire <svg>. Alternatively, you can use the same values as the ratio defined in the viewBox.
  5. Finally, the preserveAspectRatio attribute’s xMidYMid slice value tells the browser to center the image, slicing off any overflow. You can experiment with different alignment values depending on the needs of your design.

Here it is in action:

This technique isn’t perfect. Adding alt text is a tad more complicated, and SVG’s <image> element does not support srcset or sizes. But it should tide us over till object-fit is better supported, at least when server-side cropping isn’t an option.

Comments

Federico Brigante said:

The major drawback here is that the image’s ratio is fixed. Essentially you can’t do something like “width: 100%; height: 200px”