Adam lazar
Adam lazar

Reputation: 51

how to handle images when flex direction is set to column

I am working with flex layouts and images. My goal is to stack the flex-items on top of each other on smaller screen widths, by setting flex-direction: column; but there is a strange behavior i can't understand. The flex item that wraps the image seems to take the full width of the image. I have created a CodePen that illustrates the problem. Thank you in advance

Upvotes: 0

Views: 983

Answers (2)

Andy Jakubowski
Andy Jakubowski

Reputation: 484

Let the width of the flex item be dictated by the flex container, then size the image to the size of the flex item.

When you set up a flex-direction: column flex container, the height of your flex items is controlled by the flex properties (grow, shrink, basis).

The width of a flex item in a flex-direction: column flex container can either be dictated by the flex container, or it can be left to the flex item to “decide” how big it wants to be.

In this case align-items: start controls the width of your flex items. start means that the items can size themselves however they want, and they will be positioned at the start side of your flex container.

The flex item that wraps your image doesn’t have its own size (it has the default width: auto), so your image’s width: 100% can’t be resolved. In that case the image behaves as though it had width: auto, and basically renders at its full size. Then, the flex item takes on that size, and that’s why it’s so big in your flex container.

You can force all your flex items to be the width of your column flex container by not setting align-items and letting it use the default normal value, with stretches the flex items to the width of the flex container. Then your flex items have a specific size, and your image’s width: 100% can be resolved against that size.

Here’s a working example:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  background-color: #ccc;
  padding: 10px;
  display: flex;

  flex-direction: column;
}

.item {
  background-color: #ff1b68;
  padding: 40px;
  margin: 3px;
  color: #fff;
  font-size: 40px;
}

.item--2 {
  height: 200px;
}

.item--3 {
}

.item--3 img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div class="container">
  <div class="item item--1">1</div>
  <div class="item item--2">2</div>
  <div class="item item--3">
    <img
      src="https://images7.alphacoders.com/462/thumb-1920-462576.jpg"
      alt=""
    />
  </div>
</div>

By default, each flex item has align-self: auto, which means it will look at the flex container’s align-items value. So you set align-items once, and all flex items use that. But you can specify different align-self for each item, if you want to, for example, keep your text flex items align-self: start, and your image flex item align-self: stretch.

Upvotes: 2

dale landry
dale landry

Reputation: 8600

You can use a calculated width on your image element setting it to view width units => width: calc(100vw - padding - margin). So your image element will be 100% of the view width minus the padding and margin of the it and its parent element. Also set your container to min-width: 1000px;.

If the following is not what you are looking for, please let me know.

Resize the browser to test dynamic resizing of image to fit within viewable screen

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  background-color: #ccc;
  padding: 10px;
  min-height: 1000px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
}

.item {
  background-color: #ff1b68;
  padding: 40px;
  margin: 3px;
  color: #fff;
  font-size: 40px;
  /*flex-grow: 1;*/
}

.item--2 {
  height: 200px;
}

.item--3 {
  order: 1;
}

.item--3 img {
  width: calc(100vw - 130px); 
  object-fit: cover;
}
<div class="container">
  <div class="item item--1">1</div>
  <div class="item item--2">2</div>
  <div class="item item--3">
    <img src="https://images7.alphacoders.com/462/thumb-1920-462576.jpg" alt="">
  </div>
</div>

Upvotes: 1

Related Questions