简体   繁体   中英

Why does a full-width flexbox column squash its siblings?

When trying to create a table-like layout where one main column should consume all available space, the main column ends up taking up more space than desired and pushes other columns outside the bounds of the container.

The behavior I'm seeking is as if I were using a table to lay this out and I gave a column width: 100% .

If you look at the example below, you'll see that the second column of the first row is squashed even though the overflow is to be hidden. The first column seems to have some kind of sizing priority over the others.

I'm curious why this happens and what a reusable solution is. I don't want to set a fixed-width on any of the columns.

 .list { border: 1px solid #000; } .list-row { display: flex; border: 1px solid #AAA; } .list-column { border: 1px solid blue; white-space: nowrap; } .list-column--main { flex-grow: 1; } .hide-overflow { overflow: hidden; }
 <!DOCTYPE html> <html> <head> <script src="https://rawgithub.com/ai/autoprefixer-rails/master/vendor/autoprefixer.js"></script> <meta charset="utf-8"> <title>Example</title> <style type="unprocessed" id="AutoprefixerIn">%css%</style> <style id="AutoprefixerOut"></style> <script> AutoprefixerSettings = ""; //Specify here the browsers you want to target or leave empty document.getElementById("AutoprefixerOut").innerHTML = autoprefixer(AutoprefixerSettings || null).process(document.getElementById("AutoprefixerIn").innerHTML).css; </script> </head> <body> <div class="list"> <div class="list-row"> <div class="list-column list-column--main hide-overflow"> The main column that has a very very very very very very very very very very very very very very very very very very very very very long title </div> <div class="list-column"> <a href="#">Close</a> </div> </div> <div class="list-row"> <div class="list-column list-column--main hide-overflow"> A shorter title </div> <div class="list-column"> <a href="#">Close</a> </div> </div> </div> </body> </html>

Using the flex-shrink property, you can specify which columns should shrink more when something is too wide for the box.

.list-column {
  flex-grow: 0;
  flex-shrink: 0;
  flex-basis: auto;
}
.list-column--main {
  flex-grow: 1;
  flex-shrink: 100;
  flex-basis: 100%;
}

The list-column--main columns is the only column that grows, but it's also the only column that shrinks. The other column(s) will not grow past their original size and will not be allowed to shrink.

I had expected from reading the spec that flex-shrink: 1 would work well enough, but in practice, something much larger like flex-shrink: 100 actually did what I wanted.

Further reading (flexbox spec): http://www.w3.org/TR/css3-flexbox/#propdef-flex-shrink

If I were to answer this question today in 2020, I'd recommend this:

.list-column {
  flex: none;
}
.list-column--main {
  flex: auto;
}

flex: none ensures the right column never changes from the original size it needs to contain its contents. flex: auto allows the main column to grow and shrink as space allows. Much simpler than understanding and applying every property individually.

In my other answer, I incorrectly added flex-basis: 100% , which told the browser that this element should take up the entire width of the row and is why it needed flex-shrink: 100 to correctly apply the shrink.

Good overview of flex on MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/flex Better explanation of how flex works here (but weak on explaining the shortcuts): https://css-tricks.com/snippets/css/a-guide-to-flexbox/

 .list { border: 1px solid #000; } .list-row { display: flex; border: 1px solid #AAA; } .list-column { flex: none; border: 1px solid blue; white-space: nowrap; } .list-column--main { flex: auto; } .hide-overflow { overflow: hidden; text-overflow: ellipsis; }
 <div class="list"> <div class="list-row"> <div class="list-column list-column--main hide-overflow"> The main column that has a very very very very very very very very very very very very very very very very very very very very very long title </div> <div class="list-column"> <a href="#">Close</a> </div> </div> <div class="list-row"> <div class="list-column list-column--main hide-overflow"> A shorter title </div> <div class="list-column"> <a href="#">Close</a> </div> </div> </div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM