Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can flexbox horizontally and vertically center images without stretching them?

Tags:

css

flexbox

I want to make images centered horizontally and vertically inside their containers. And if their width or height is greater than their containers' width or height, then make them automatically shrink while keeping their proportions.

The following CSS code is what I use on the container to try to achieve the goal:

display: -ms-flexbox;
display: -webkit-flex;
display:         flex;
    -ms-flex-direction: column;
-webkit-flex-direction: column;
        flex-direction: column;
          -ms-flex-pack: center;
-webkit-justify-content: center;
        justify-content: center;

And here are three examples on jsFiddle:

  • The first example is an image whose width is greater than its height. It works fine.
  • The second example is an image whose height is greater than its width. But in this example, its width stretches to container's width, and that isn't what I want.
  • The third example has the same problem as the second example.

Besides, I know the goal can also be achieved by using CSS position and transform. But such a method often creates 1 pixel gap between the resized image and the container's border. That is, the resized image fails to touch the container's border, at where it should do. Therefore I have to resort to CSS flexbox.

like image 820
Ian Y. Avatar asked Jun 02 '15 03:06

Ian Y.


People also ask

How do I stop image stretching in CSS flexbox?

Fortunately, the solution is simple. You just need to replace your image/flex item's align-self property's default stretch value with another value. Instead of stretch you can use center , which will remove the image stretching, and vertically align your image in the middle of its parent container.

How do you center a div vertically and horizontally with flexbox?

To center a div vertically and horizontally using flexbox, you need to wrap the div or div's inside a container with properties ' display: flex; flex-direction: column; justify-content: center;align-items: center; ', then just make the div ' text-align: center; ' if it has text.

How do you align all items horizontally to the middle of a flexbox container?

We use justify-content to align the item on the main axis, which in this case is the inline axis running horizontally. You can take a look at the code of this example below. Change the size of the container or nested element and the nested element always remains centered.

How can we center everything inside a container both vertically and horizontally?

To center both vertically and horizontally, use padding and text-align: center : I am vertically and horizontally centered.


1 Answers

The problem is that the initial value of align-items is stretch and the initial value of align-self is auto, so the images are stretched.

So you need one of the following:

.flex-container {
    align-items: center;
}
.flex-item {
    align-self: center;
}

* {
  margin: 0;
  padding: 0;
}
div {
  display: flex; /* Magic begins */
  flex-direction: column;
  justify-content: center; /* Center in main axis */
  align-items: center; /* Center in cross axis */
  margin: 20px auto;
  width: 300px;
  height: 300px;
  border: 2px solid #000;
}
img {
  max-width: 100%;
  max-height: 100%;
}
<div>
  <img src="http://lorempixel.com/400/200/" alt="" />
</div>
<div>
  <img src="http://lorempixel.com/200/400/" alt="" />
</div>
<div>
  <img src="http://lorempixel.com/50/50/" alt="" />
</div>

But note that the middle image is still a bit stretched. That's because if the images are taller than the container, they will shrink vertically but not horizontally (it would be the opposite with a row layout).

To prevent that, use object-fit (not supported by IE and Edge):

img {
  object-fit: contain;
}

* {
  margin: 0;
  padding: 0;
}
div {
  display: flex; /* Magic begins */
  flex-direction: column;
  justify-content: center; /* Center in main axis */
  align-items: center; /* Center in cross axis */
  margin: 20px auto;
  width: 300px;
  height: 300px;
  border: 2px solid #000;
}
img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
<div>
  <img src="http://lorempixel.com/400/200/" alt="" />
</div>
<div>
  <img src="http://lorempixel.com/200/400/" alt="" />
</div>
<div>
  <img src="http://lorempixel.com/50/50/" alt="" />
</div>
like image 154
Oriol Avatar answered Nov 29 '22 14:11

Oriol