233

Flexbox has this behaviour where it stretches images to their natural height. In other words, if I have a flexbox container with a child image, and I resize the width of that image, the height doesn't resize at all and the image gets stretched.

div {
  display: flex; 
  flex-wrap: wrap;
}

img {
  width: 50%
}
<div>
    <img src="https://i.imgur.com/KAthy7g.jpg" >
    <h1>Heading</h1>
    <p>Paragraph</p>
</div>

What causes this?

Aryan Beezadhur
  • 4,503
  • 4
  • 21
  • 42
sjbuysse
  • 3,872
  • 7
  • 25
  • 37
  • 9
    In Firefox and IE works fine. In Chrome you can fix with `align-self:flex-start` in the image. I don't know why, maybe the default value in chrome is stretch. –  Jun 03 '16 at 08:40
  • 2
    Also adding height: 100%; to the img fixes the problem, I would like to know why it stretches the image too. – Paran0a Jun 03 '16 at 08:43
  • 3
    @blonfu, the default value in all browsers is `align-items: stretch` / `align-self: stretch`. If you add a border around each item and remove `wrap`, you'll notice all items stretch in all browsers: http://codepen.io/anon/pen/oLXBVx?editors=1100 – Michael Benjamin Jun 03 '16 at 14:19
  • Ok.I learn this but with images work differently in chrome and the others browser. Chrome don't respect the aspect ratio if you don't define the height. –  Jun 03 '16 at 18:25
  • @blonfu, Yes. No question there are browser inconsistencies and more granular levels. – Michael Benjamin Jun 03 '16 at 18:40

8 Answers8

502

It is stretching because align-self default value is stretch. Set align-self to center.

align-self: center;

See documentation here: align-self

TylerH
  • 20,799
  • 66
  • 75
  • 101
pradeep1991singh
  • 8,185
  • 4
  • 21
  • 31
  • Yes but the others browser mantaining the aspect ratio in the images. Chrome nor applies flex-basis in img –  Jun 03 '16 at 09:29
  • 23
    I think `align-self: start;` may be a stronger answer because images should vertically align to the TOP of their containers (not center) like any styleless image (no css) would. Either way, both answers fix the stretching. So it depends on what OP wants of course - just didn't get that 'vertically centered' impression from OP's post. – toad Apr 05 '18 at 08:45
  • If you don't define a width on an image and it's in a flex-container, it will stretch to 100%. `align-self: [flex-start, center...others]` will prevent the image from taking 100% of the flex-containers width. `align-self:center` fixes it of course, but if you want your image to start from the beginning or end of container use `align-items: flex-start or flex-end` – Clifford Fajardo Aug 02 '18 at 11:54
  • 3
    You can also put `align-items: center` (or whatever alignment fits your needs) on the parent. – derpedy-doo Apr 12 '19 at 04:19
  • Doesn't work for me: – David Spector Apr 16 '21 at 21:59
  • I cant really understand why adding a align-self: anyvalue; really solves the problem. Could someone please explain it to me? – Daniel_Ranjbar Jul 17 '22 at 13:45
24

The key attribute is align-self: center:

.container {
  display: flex;
  flex-direction: column;
}

img {
  max-width: 100%;
}

img.align-self {
  align-self: center;
}
<div class="container">
    <p>Without align-self:</p>
    <img src="http://i.imgur.com/NFBYJ3hs.jpg" />
    <p>With align-self:</p>
    <img class="align-self" src="http://i.imgur.com/NFBYJ3hs.jpg" />
</div>
FutureCake
  • 2,614
  • 3
  • 27
  • 70
Dorian
  • 22,759
  • 8
  • 120
  • 116
2

Adding margin to align images:

Since we wanted the image to be left-aligned, we added:

img {
  margin-right: auto;
}

Similarly for image to be right-aligned, we can add margin-right: auto;. The snippet shows a demo for both types of alignment.

Good Luck...

div {
  display:flex; 
  flex-direction:column;
  border: 2px black solid;
}

h1 {
  text-align: center;
}
hr {
  border: 1px black solid;
  width: 100%
}
img.one {
  margin-right: auto;
}

img.two {
  margin-left: auto;
}
<div>
  <h1>Flex Box</h1>
  
  <hr />
  
  <img src="https://via.placeholder.com/80x80" class="one" 
  />
  
  
  <img src="https://via.placeholder.com/80x80" class="two" 
  />
  
  <hr />
</div>
Aakash
  • 21,375
  • 7
  • 100
  • 81
2

It is stretching because align-self default value is stretch. there is two solution for this case : 1. set img align-self : center OR 2. set parent align-items : center

img {

   align-self: center
}

OR

.parent {
  align-items: center
}
mohamed ali
  • 202
  • 2
  • 3
2

I had a similar issue while making my navigation bar, but none of the above worked for me.

My solution was adding height: 100% for the image.

If you're aligning the items horizontally, add width: 100% instead.

EDIT: Chrome seems to add this value by default now, but you'll need to add this for compatibility.

Jongwoo Lee
  • 774
  • 7
  • 20
  • Yes, Thank you! This worked for me. But I had to put the image in a wrapper, set the height and width of the wrapper then set the image itself to 100% width. – Embedded_Mugs Jul 01 '21 at 02:53
2

Use one of the CSS settings below: contain or cover is most popular

.my-img {
  object-fit: contain;
}

or

.my-img {
  object-fit: cover;
}
Xin
  • 33,823
  • 14
  • 84
  • 85
1

I faced the same issue with a Foundation menu. align-self: center; didn't work for me.

My solution was to wrap the image with a <div style="display: inline-table;">...</div>

isapir
  • 21,295
  • 13
  • 115
  • 116
0

I had a similar issue, my solution was adding flex-shrink: 0; to the image.

Zach Jensz
  • 3,650
  • 5
  • 15
  • 30