Aspect ratio Vs Cropping: How to avoid pixelated/stretched images yet have the same dimension

I often happen when we require that our items(images) in a row should be square or if not square then of the same size. we achieve it like this →

width: 200px; height auto; In this case, the image sometimes become pixelated or stretched.

I think cropping could be the solution.

How to achieve cropping so that the dimensions of all the images in a row remain same, and still the images are not pixelated/stretched.

One such example is how Instagram handles this →

see for example this image

what is the process to accomplish this through CSS/HTML combination

In this case, with height set to auto, the image should retain it’s native aspect ratio. Also a picture should not pixelate unless its native resolution is less than the size it is displayed. so at 200px width, a picture of 100px would pixelate, but anything 200px or more would not.

If you want to force a uniform aspect ratio on a foreground image (which may or may not differ from its native aspect) without stretching or distorting you can use the object-fit css property. But note it does not have universal browser support yet.

2 Likes

In the instagram page the thumbnail images are in a square aspect, even if the original photo is not. I imagine that the images are cropped to square on the server-side as the thumbnails are created rather than by css on the client side.

1 Like

You can fake ‘object-fit’ with a little css trickery.

It achieves much the same effect as background-size:cover (or object-fit).

3 Likes

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.

Hi there everyone.

#Objective: squared images w/o pixelation.

I think here we were using and leveraging the absolute and relative property of the positioning, Right?

w/o seeing your code I tried to build one, but looks like I failed →

I am even not able to make the image visible.

Isn’t that what you meant for the “hidden” to do?

1 Like

Removed, but I still couldn’t make it square.

Can you see the image? I can’t, unless I open the image directly in my browser. Try an image from a different source location.

1 Like

Hi there,
yes I can see image.

Did I understand you say that you did not look at Paul’s code?

The fake trick only really works with images that are within a reasonable size but where you have very large images like yours the trick fails as the image is too big (the answer is in my codepen as you have missed out some vital ingredients).

If you know that the width will always be longer than the height then you can do it differently like this:

.squareframe {
  width: 150px;
  height: 150px;
  position: relative;
  overflow:hidden;
  background:red
}
.squareframe img {
	position:absolute;
  top:50%;
	left:50%;
	height:100%;/* if width is greater than height then reverse height and width values*/
	width:auto;
	transform:translate(-50%, -50%);
  }
<div class="squareframe">
    <img src="https://s-i.huffpost.com/gen/2502734/images/o-MICHELLEOBAMA_ORIGINAL-facebook.jpg"  alt="">
</div>

Or even better use object-fit with a fallback.

e.g.

.squareframe {
  width: 150px;
  height: 150px;
  position: relative;
  overflow: hidden;
  background: red;
}
.squareframe img {
  position: absolute;
  top: 50%;
  left: 50%;
  height: 100%;
  width: auto;
  transform: translate(-50%, -50%);
}

@supports (object-fit: cover) {
  .squareframe img {
    position: static;
    height: 100%;
    width: 100%;
    transform: none;
    object-fit: cover;
  }
}

This is not the same method as in my example which will not work with the very large images you are using.

1 Like

Partially yes.

what I was trying to say is that I am not copying pasting @PaulOB’s code, but grasp the logic and do it on my own so that my brain can adapt the concept. Did you get it now? It’s not that I didn’t look at all in his code.

So, sir, this method is air-tight? It will always work.

It will work for images where the width of the image is equal to or greater than the height.

It would not wok for an image that was say 100px x 200px. You would then need to reverse the height and width rules.

You could adapt my original and supply a max-width which would cover most images especially if using a fallback.

e.g.


.squareframe {
  width: 150px;
  height: 150px;
  position: relative;
  overflow: hidden;
  background: red;
}
.squareframe img {
  position: absolute;
  top: 50%;
  left: 50%;
  min-width: 100%;
  min-height:100%;
  width: auto;
  height:auto;
  max-width:200%;/* would allow for portrait to still fit even if width is half the height*/
  transform: translate(-50%, -50%);
}
@supports (object-fit: cover) {
  .squareframe img {
    position: static;
    height: 100%;
    width: 100%;
    transform: none;
    object-fit: cover;
  max-width:none;
  }
}

There is no foolproof solution for every case apart from a js polyfill fallback.

1 Like

Is there way we can address there responsiveness also?
https://s3.amazonaws.com/sitepoint007/resp.gif

May be if there is a way to set height and width in %age.

Hi,

The images are doing what they should be doing on your codepen example and maintain their aspect ratio as best they can.

The problem is that you are scaling the width but leaving the height at 300px so the images get thinner but still maintain aspect ratio.

If you want the width and height to scale then you will need to make the element square. Something like this perhaps.

.margin {display:flex; }
.squareframe {
  width: 25%;
  position: relative;
  overflow: hidden;
  background: red;
  margin: 20px;
}
.squareframe:after {
  content: "";
  display: block;
  padding-bottom: 100%;
}
.squareframe img {
  position: absolute;
  top: 50%;
  left: 50%;
  min-width: 100%;
  min-height:100%;
  width: auto;
  height:auto;
  max-width:200%;/* would allow for portrait to still fit even if width is half the height*/
  transform: translate(-50%, -50%);
}

@supports (object-fit: cover) {
  .squareframe img {
    position: absolute;
    top:0;
    left:0;
    bottom:0;
    width: 100%;
    transform: none;
    object-fit: cover;
  max-width:none;
  }

Untested:)

1 Like

Thanks for all your help. This is a very difficult concept. It is for the first time that after receiving so much of help I couldn’t successfully implement this.

In Instagram are they managing that through Javascript?

You may need to explain again what you want as the criteria seems to have changed from the first post of a square image.

Object fit will do what you want either way so it’s only ie11 that you need to worry about.

Alternatively just use background images and background-size: cover.

1 Like