novicePrgrmr
novicePrgrmr

Reputation: 19385

How to "crop" a rectangular image into a square with CSS?

I know that it is impossible to actually modify an image with CSS, which is why I put crop in quotes.

What I'd like to do is take rectangular images and use CSS to make them appear square without distorting the image at all.

I'd basically like to turn this:

enter image description here

Into this:

enter image description here

Upvotes: 259

Views: 407248

Answers (14)

user3777368
user3777368

Reputation: 41

I came with a different approach. You basically have to crop the rectangular image to fit it inside the square is all there is to it. Best approach is if the image width is greater than the height, then you crop the image alittle from left and right side of the image. If the image height is greater than the image width then you crop the bottom of the image. Here is my solution. I needed a little help from PHP though.

    <div style="position: relative; width: 154px; height: 154px; overflow: hidden;">
<?php 
        // get image dimensions whichever way you like. I used imgaick
        $image = new Imagick("myimage.png");
        $width = $image->getImageWidth();  
        $height = $image->getImageHeight(); 
        if($width > $height){
 ?>
        <img src="myimage.png" style="display: block; position: absolute; top: 0px; left: 50%; transform: translateX(-50%); -ms-transform: translateX(-50%); -webkit-transform: translateX(-50%); height: 100%; " />
 <?php
        }else{
 ?>
        <img src="myimage.png" style="display: block; position: absolute; top: 0px; left: 0px; width: 100%; " />
 <?php
        }
 ?>

    </div>

Upvotes: 0

Ben Carp
Ben Carp

Reputation: 26518

2023 Answer

img {
    width: 200px; /* Dtermine size of square */
    aspect-ratio: 1/1; /* Keeps height equal to width */
    object-fit: cover; /* No distortion of image, and no empty space */
}
<img src="https://i.sstatic.net/GA6bB.png">

Upvotes: 5

Mattia Rasulo
Mattia Rasulo

Reputation: 1451

Today you can use aspect-ratio:

img {
   aspect-ratio: 1 / 1;
}

It has wide support amongst modern browsers as well: https://caniuse.com/mdn-css_properties_aspect-ratio

Upvotes: 9

Peter Kionga-Kamau
Peter Kionga-Kamau

Reputation: 7068

A pure CSS solution with no wrapper div or other useless code:

img {
  object-fit: cover;
  width: 230px;
  height: 230px;
}

Upvotes: 585

Ajith Gopi
Ajith Gopi

Reputation: 1826

Check out CSS aspect-ratio

https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio

.square-image{
  width: 50%;
  background-image: url('https://picsum.photos/id/0/367/267');
  background-size: cover;
  background-position: center;
  aspect-ratio: 1/1;
}
<div class="square-image"></div>

You can also do this with a regular img tag as follows

.square-image{
  width: 50%;
  object-fit: cover; /* Required to prevent the image from stretching, use the object-position property to adjust the visible area */
  aspect-ratio: 1/1;
}
<img src="https://picsum.photos/id/0/367/267" class="square-image"/>

Upvotes: 24

Furqan Rahamath
Furqan Rahamath

Reputation: 2076

object-fit: cover will do exactly what you need.

But it might not work on IE/Edge. Follow as shown below to fix it with just CSS to work on all browsers.

The approach I took was to position the image inside the container with absolute and then place it right at the centre using the combination:

position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

Once it is in the centre, I give to the image,

// For vertical blocks (i.e., where height is greater than width)
height: 100%;
width: auto;

// For Horizontal blocks (i.e., where width is greater than height)
height: auto;
width: 100%;

This makes the image get the effect of Object-fit:cover.


Here is a demonstration of the above logic.

https://jsfiddle.net/furqan_694/s3xLe1gp/

This logic works in all browsers.


Original Image
Original Image

Vertically Cropped
Vertically Cropped Image

Horizontally Cropped
Horizontally Cropped Image

Square Container Square Cropped Image


Upvotes: 5

Michael
Michael

Reputation: 7092

Assuming they do not have to be in IMG tags...

HTML:

<div class="thumb1">
</div>

CSS:

.thumb1 { 
  background: url(blah.jpg) 50% 50% no-repeat; /* 50% 50% centers image in div */
  width: 250px;
  height: 250px;
}

.thumb1:hover { YOUR HOVER STYLES HERE }

EDIT: If the div needs to link somewhere just adjust HTML and Styles like so:

HTML:

<div class="thumb1">
<a href="#">Link</a>
</div>

CSS:

.thumb1 { 
  background: url(blah.jpg) 50% 50% no-repeat; /* 50% 50% centers image in div */
  width: 250px;
  height: 250px;
}

.thumb1 a {
  display: block;
  width: 250px;
  height: 250px;
}

.thumb1 a:hover { YOUR HOVER STYLES HERE }

Note this could also be modified to be responsive, for example % widths and heights etc.

Upvotes: 90

jnaklaas
jnaklaas

Reputation: 1769

If the image is in a container with a responsive width:

.rect-img-container {
  position: relative;
}

.rect-img-container::after {
  content: "";
  display: block;
  padding-bottom: 100%;
}

.rect-img {
  position: absolute;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div class="rect-img-container">
  <img class="rect-img" src="https://picsum.photos/id/0/367/267" alt="">
</div>

(edit: updated from sass to plain css) (edit: Added dummy image for reference)

Upvotes: 83

tech292
tech292

Reputation: 31

Either use a div with square dimensions with the image inside with the .testimg class:

.test {
width: 307px;
height: 307px;
overflow:hidden
}

.testimg {
    margin-left: -76px

}

or a square div with a background of the image.

.test2 {
width: 307px;
height: 307px;
    background: url(https://i.sstatic.net/GA6bB.png) 50% 50%
}

Here's some examples: http://jsfiddle.net/QqCLC/1/

UPDATED SO THE IMAGE CENTRES

.test {
  width: 307px;
  height: 307px;
  overflow: hidden
}

.testimg {
  margin-left: -76px
}

.test2 {
  width: 307px;
  height: 307px;
  background: url(https://i.sstatic.net/GA6bB.png) 50% 50%
}
<div class="test"><img src="https://i.sstatic.net/GA6bB.png" width="460" height="307" class="testimg" /></div>

<div class="test2"></div>

Upvotes: 0

prozac
prozac

Reputation: 279

I had a similar issue and could not "compromise" with background images. I came up with this.

<div class="container">
    <img src="http://lorempixel.com/800x600/nature">
</div>

.container {
    position: relative;
    width: 25%; /* whatever width you want. I was implementing this in a 4 tile grid pattern. I used javascript to set height equal to width */
    border: 2px solid #fff; /* just to separate the images */
    overflow: hidden; /* "crop" the image */
    background: #000; /* incase the image is wider than tall/taller than wide */
}

.container img {
    position: absolute;
    display: block;
    height: 100%; /* all images at least fill the height */
    top: 50%; /* top, left, transform trick to vertically and horizontally center image */
    left: 50%;
    transform: translate3d(-50%,-50%,0);
}

//assuming you're using jQuery
var h = $('.container').outerWidth();
$('.container').css({height: h + 'px'});

Hope this helps!

Example: https://jsfiddle.net/cfbuwxmr/1/

Upvotes: 3

Philip Nuzhnyy
Philip Nuzhnyy

Reputation: 4740

Using background-size:cover - http://codepen.io/anon/pen/RNyKzB

CSS:

.image-container {
  background-image: url('https://i.sstatic.net/GA6bB.png');
  background-size:cover;
  background-repeat:no-repeat;
  width:250px;
  height:250px;
}  

Markup:

<div class="image-container"></div>

Upvotes: 33

FreddyBushBoy
FreddyBushBoy

Reputation: 577

I actually came across this same problem recently and ended up with a slightly different approach (I wasn't able to use background images). It does require a tiny bit of jQuery though to determine the orientation of the images (I' sure you could use plain JS instead though).

I wrote a blog post about it if you are interested in more explaination but the code is pretty simple:

HTML:

<ul class="cropped-images">
  <li><img src="http://fredparke.com/sites/default/files/cat-portrait.jpg" /></li>
  <li><img src="http://fredparke.com/sites/default/files/cat-landscape.jpg" /></li>
</ul>

CSS:

li {
  width: 150px; // Or whatever you want.
  height: 150px; // Or whatever you want.
  overflow: hidden;
  margin: 10px;
  display: inline-block;
  vertical-align: top;
}
li img {
  max-width: 100%;
  height: auto;
  width: auto;
}
li img.landscape {
  max-width: none;
  max-height: 100%;
}

jQuery:

$( document ).ready(function() {

    $('.cropped-images img').each(function() {
      if ($(this).width() > $(this).height()) {
        $(this).addClass('landscape');        
      }
    });

});

Upvotes: 14

Diodeus - James MacFarlane
Diodeus - James MacFarlane

Reputation: 114347

Use CSS: overflow:

.thumb {
   width:230px;
   height:230px;
   overflow:hidden
}

Upvotes: 2

j08691
j08691

Reputation: 207861

  1. Place your image in a div.
  2. Give your div explicit square dimensions.
  3. Set the CSS overflow property on the div to hidden (overflow:hidden).
  4. Put your imagine inside the div.
  5. Profit.

For example:

<div style="width:200px;height:200px;overflow:hidden">
    <img src="foo.png" />
</div>

Upvotes: 60

Related Questions