Eric
Eric

Reputation: 5215

How can I stretch/shrink any size image to best fit a square, with only CSS/HTML?

I have a perfectly square DIV - 500 x 500px.

I am going to be displaying images of unknown size in that DIV... some of the images are horizontal and some are vertical; some are larger than 500px tall or wide, some are smaller than 500px tall or wide. I don't control the image size.

How can I have any image I place in the DIV be expanded or reduced to best fill the box? My goal is that one axis of the image is always 500px, and the other axis is resized to fit. (This means that if the image is not perfectly square, there will always be blank space on either side of the image for vertical images, or above and below the image for horizontal images. That's ok.)

I know I can use JS or something server-side to do some math on the image sizes and compute new dimensions on the fly that way, but I'm seeking a CSS-only solution. Can flexboxes accomplish this?

Upvotes: 4

Views: 1602

Answers (4)

cloned
cloned

Reputation: 6752

You can achieve this by using object-fit. For object-fit to work you have to set a size to your image, since I want it to cover the whole box I simply set width: 100%

.image {
  height: 500px;
  width: 500px;
  border: 1px solid red;                  /* to mark each box in this sample */
}

.image img {
  object-fit: cover;
  width: 100%;
}
<div class="image">
 <img src="https://via.placeholder.com/400x600" alt="">
</div>

<div class="image">
 <img src="https://via.placeholder.com/700x400" alt="">
</div>

Upvotes: 0

Raphael Setin
Raphael Setin

Reputation: 875

Using the background-image property makes the loading rely on CSS, which has some drawbacks, such as performance. Because of that, I came up with the following solution:

<div
  style={{
    display: "flex",
    width: "100%",
    height: "100%",
  }}
>
  <img
    style={{
      minWidth: "100%",
      minHeight: "100%",
      objectFit: "cover",
    }}
    alt=""
    src={url}
  />
</div>

The above will scale up an image in order for it to cover the parent container.
If you just need to fit inside, then change objectFit to contain.

Upvotes: 0

Asons
Asons

Reputation: 87303

Since the CSS object-fit property is still note widely supported, and you have a fixed container, why not use background-image:.../background-size:contain

.image {
  height: 500px;
  width: 500px;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: center center;
  border: 1px solid red;                  /* to mark each box in this sample */
}

.nr1 {
  background-image: url(http://lorempixel.com/400/600/animals/1);
}
.nr2 {
  background-image: url(http://lorempixel.com/600/400/animals/3);
}
<div class="image nr1">
</div>

<div class="image nr2">
</div>

Upvotes: 1

Rahul K
Rahul K

Reputation: 928

Here is the solution: See Result at http://codepen.io/anon/pen/MyBXKZ

HTML

<div class="image-wrapper">
<div class="image-container">
  <img src="http//images.fonearena.com/blog/wp-content/uploads/2013/11/Lenovo-p780-camera-sample-10.jpg" alt="Sample image">
</div>

CSS

.image-wrapper {
  background-color: #fff;
  -webkit-box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.33);
  -moz-box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.33);
  box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.33);
  height: 500px;
  width: 500px;
}

.image-container {
  text-align: center;
  line-height: 500px;
  height: 100%;
}

.image-container img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  vertical-align: middle;
}

Upvotes: 0

Related Questions