Prevent a Flex Items Height from Expanding to Match Other Flex Items

Prevent a flex items height from expanding to match other flex items

This is an old solution.
My answer is superseded by this new answer by Aaron using align-self. That is a better solution that does not rely on a CSS quirk.

As long as the flex container has no height itself, you can set height: 0% on the first flex item. Because it has no height to inherit from its parent, any percentage height will cause it to collapse. It will then grow with its contents.

Example

In this example I have removed the -webkit prefix. It's only really required for Safari and the prefix can be added above the non-prefixed version. I also removed flex-direction: row as it is the default value.

.container {
display: flex;
}
.flexbox-1 {
flex: 1;
height: 0%;
border: solid 3px red;
}
.flexbox-2 {
flex: 2;
border: solid 3px blue;
height: 200px;
margin-left: 10px;
}
<div class="container">
<div class="flexbox-1">.flexbox-1</div>
<div class="flexbox-2">.flexbox-2</div>
</div>

How to prevent item height expansion from expanding other item in the same row - CSS grid/flex?

So after some more searching I figured that the actually layout style that I needed aligns with the Masonry/Mosaic pattern. Since I now know the name I could do more specific Googling and found a blog post written by Tobias Ahlin with a solution.

https://tobiasahlin.com/blog/masonry-with-css/

The gist is that you need to have the flow direction be columns while being wrapped and then place orderings on the elements using :nth-child.


/* Render items as columns */
.container {
display: flex;
flex-flow: column wrap;
}

/* Re-order items into rows */
.item:nth-child(3n+1) { order: 1; }
.item:nth-child(3n+2) { order: 2; }
.item:nth-child(3n) { order: 3; }

/* Force new columns */
.container::before,
.container::after {
content: "";
flex-basis: 100%;
width: 0;
order: 2;
}

If I'm honest, I'm not really sure why this works. It will also behave unexpectedly depending on the heights of the container and the items.

Hope this helps anyone else who's having issues with this deceptively simple design layout!

How to disable equal height columns in Flexbox?

You're encountering the flex equal height columns feature.

An initial setting of a flex container is align-items: stretch.

This means that flex items automatically expand the full length of the cross axis of the container. In a row-direction container, the cross axis is vertical (height).

The tallest item sets the height for all siblings. As the tallest item expands, its siblings follow along. Hence, equal height for all items.

To override this default setting, add align-items: flex-start to the flex container:

#container_add_movies {
display: flex;
align-items: flex-start;
}

#container_add_movies {
display: flex;
align-items: flex-start; /* NEW */
}

#container_add_movies #feedback {
width: 20%;
background-color: green;
display: block;
}

#container_add_movies #search {
width: 60%;
background-color: red;
}

#container_add_movies #suggestions {
width: 20%;
background-color: yellow;
}
<div id='container_add_movies'>
<div id='feedback'>Feedback</div>
<div id='search'>
Search<br>Search<br>Search<br>Search<br>Search<br> Search
<br>Search<br>Search<br>Search<br>Search<br>
</div>
<div id='suggestions'>Suggestions</div>
</div>

How to prevent a centered aligned flex item from going up as its height increases?

I Think that's what you want to achieve:

I positioned your menu underneath the button with position absolute. so the button won't change its position.

const dropdown = () => {
let display = document.getElementById("menu").style.display;

document.getElementById("menu").style.display = (display === "none") ? "block":"none";
//toggling "visibility" takes the div out of its place
}
.nav {
display: flex;
justify-content: center;
align-items: center;
height: 160px;
border: 1px solid black;
text-align: center;
}

.dropdownContainer {
margin-left: auto;
position: relative;
}

#drop {
display: none;
/* visibility:hidden;*/
}
#menu {
position: absolute;
top: 100%;
}
<nav class="nav">
<div>Irrelevant elements to this question</div>
<div class="dropdownContainer">
<button onclick="dropdown()" class="dropdownBtn">Ronaldinho</button>
<div id="menu">
<!-- the more items added here, the more up the page the whole container goes -->
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
<div>Six</div>
</div>
</div>
</nav>

Prevent flex item from exceeding parent height and make scroll bar work

Short Answer

Instead of flex: 1, use flex: 1 1 1px.

Make these two adjustments in your code:

#messagelist {
/* flex:1; */
flex: 1 1 1px; /* new */
}

#messagecontents {
/* flex:1; */
flex: 1 1 1px; /* new */
}

revised codepen


Explanation

In most cases, as you have noted, adding min-height: 0 to flex items in a column-direction container is enough to correct the problem.

In this case, however, there's an additional obstacle: flex-basis.

You're applying the following rule to flex items #messagelist and #messagecontents: flex: 1.

This is a shorthand rule that breaks down to:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0

(source: https://www.w3.org/TR/css-flexbox-1/#flex-common)


2019 UPDATE: Since the posting of this answer in 2018, it appears that Chrome's behavior has changed and is now uniform with Firefox and Edge. Please keep that in mind as you read the rest of this answer.


In Chrome, flex-basis: 0 is enough to trigger an overflow, which generates the scrollbars. (2019 update: This may no longer be the case.)

In Firefox and Edge, however, a zero flex-basis is insufficient. This is probably the more correct behavior in terms of standards compliance as MDN states:

In order for overflow to have an effect, the block-level container must have either a set height (height or max-height) or white-space set to nowrap.

Well, flex-basis: 0 meets none of those conditions, so an overflow condition should not occur. Chrome has probably engaged in an intervention (as they often do).

An intervention is when a user agent decides to deviate slightly from a standardized behavior in order to provide a greatly enhanced user experience.

To meet the "standardized behavior", which would enable an overflow to occur in Firefox and Edge, give flex-basis a fixed height (even if it's just 1px).

Prevent image from expanding horizontal flex box

Removing the items-center class makes flex items the same height. To prevent img from changing the left column's height its position should be absolute. To define the position of img the parent tag should be relative. Two classes of translate-x-1/2 and right-1/2 are added to bring the img center.

<script src="https://cdn.tailwindcss.com/"></script>
<div class="flex">
<div class="w-1/3 bg-stone-200 relative">
<img class="absolute translate-x-1/2 right-1/2 h-full" src="https://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon.png" />
</div>
<div class="w-1/3 bg-stone-50">
<p>Short Text</p>
</div>
<div class="w-1/3 bg-blue-900">
<p>Short Text</p>
</div>
</div>

How to prevent flexbox from being equal height with the flexbox next to it?

You need to add align-self: flex-start; to the inside flex boxes. This overrules the default value align-self: stretch;

Here is an example:

#outsideFlexBox {  display: flex;}
.insideFlexBox { display: flex; align-self: flex-start; margin: 10px; padding: 10px; background-color: #33FFCC;}
<div id="outsideFlexBox">  <div class="insideFlexBox">    <ul>      <li>Item 1</li>      <li>Item 2</li>      <li>Item 3</li>      <li>Item 4</li>      <li>Item 5</li>    </ul>  </div>  <div class="insideFlexBox">    <ul>      <li>Item 1</li>      <li>Item 2</li>      <li>Item 3</li>    </ul>  </div></div>

How flex: 1 affects height of flex items?

Firstly, you've defined the container with display: flex. The default flex-direction is row.

This means the the main axis is horizontal.

Hence, the flex property is controlling width. It has no affect on height.

You would have to shift the main axis (by adding flex-direction: column) in order to apply the flex property vertically.

Secondly, if you change the height: 500px to min-height: 500px, you will solve the overflow problem (without having to change flex-direction).

#about {
min-height: 500px;
border: 2px solid blue;
}

.row {
display: flex;
border: 2px solid black;
}

img {
display: block;
width: 100%;
height: 100%;
}

.column {
flex: 1;
border: 2px dashed red;
}
<section id="about">
<div class="row">
<div class="column">
<img src="https://i.stack.imgur.com/yat2N.jpg" alt="Sample Image">
</div>
<div class="column"> Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur quibusdam dicta dolore suscipit quidem, hic nihil aliquid officia porro illum! Necessitatibus cupiditate, sapiente cum recusandae tenetur dolore veritatis in temporibus perferendis.
Ex corrupti voluptatibus eaque aliquam quis soluta veniam non dicta repellendus ea iure temporibus assumenda placeat accusantium quae iste, corporis maxime dolorum quisquam neque est sint asperiores doloribus. Quibusdam ducimus saepe distinctio
illum veniam voluptates amet quod perferendis dolorem, deleniti mollitia. Ab aperiam, ea itaque tempore molestias ullam sint accusamus totam reiciendis laborum. At natus consequatur ex officia. Porro dolor accusamus blanditiis nam commodi provident
assumenda facere adipisci perferendis. </div>
</div>
</section>


Related Topics



Leave a reply



Submit