简体   繁体   中英

Make flex items have equal width in a row

If you look at the example below, I want the headers ( h4.child-title ) to have the same length within the parent container.

But I'm not successful in achieving this.

Any help is appreciated.

 .top-level { display: flex; flex-flow: row wrap; } .section { display: flex; flex-flow: row nowrap; border: 1px solid; margin-right: 12px; margin-top: 12px; } .section-child { display: flex; flex-flow: column nowrap; align-items: center; flex: 1 1 0; } .child-title { white-space: nowrap; } .vertical-separator { width: 1px; background-color: rgba(0, 0, 0, 0.3); margin: 8px; } 
 <div class="top-level"> <section class="section"> <div claas="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> <section class="section"> <div claas="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> <section class="section"> <div claas="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> </div> 

Flexbox method

In order to make the text items ( .section-child ) equal width, you need to use flex: 1 1 0 , which you have done. This is the same as saying flex: 1 .

However, this by itself doesn't achieve the goal for two reasons:

  1. The parent of .section-child , a flex container, but also a flex item in a larger container, is limited to the width of its content, by default. So it won't expand and the text can overflow the container. You need to apply flex: 1 to .section , as well.

  2. A flex item cannot be smaller than the size of its content, by default. The initial setting is min-width: auto . So flex: 1 cannot work to equally distribute container space, because a flex item cannot shrink past the longest item. You need to override this behavior with min-width: 0 .

 .top-level { display: flex; flex-flow: row wrap; } .section { display: flex; flex-flow: row nowrap; border: 1px solid; margin-right: 12px; margin-top: 12px; flex: 1; min-width: 0; } .section-child { display: flex; flex-flow: column nowrap; align-items: center; flex: 1; min-width: 0; } .child-title { white-space: nowrap; } .vertical-separator { width: 1px; background-color: rgba(0, 0, 0, 0.3); margin: 8px; } 
 <div class="top-level"> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> </div> 

Now all flex items are equal width. However, because you have the text set to nowrap , it can overflow its boundaries. If you remove nowrap , everything fits nicely.

 .top-level { display: flex; flex-flow: row wrap; } .section { display: flex; flex-flow: row nowrap; border: 1px solid; margin-right: 12px; margin-top: 12px; flex: 1; min-width: 0; } .section-child { display: flex; flex-flow: column nowrap; align-items: center; flex: 1; min-width: 0; } .child-title { /* white-space: nowrap; */ } .vertical-separator { width: 1px; background-color: rgba(0, 0, 0, 0.3); margin: 8px; } 
 <div class="top-level"> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> </div> 

More information:


CSS Grid method

If your actual goal is to make all flex items in the row equal to the width of the longest item, that's something flexbox cannot do.

Flex can do equal width and equal height flex items, because it provides flex: 1 on the main axis.

Flex can also do equal width and equal height columns / rows, because it provides align-items: stretch on the cross axis.

But there is nothing in the flexbox spec about equal size flex items based on the size of a particular sibling. However, flexbox's sister technology, CSS Grid, can do it.

By using Grid's fr unit, the width of columns in a grid can be set to the width of the longest column.

 .top-level { display: flex; flex-flow: row wrap; } .section { display: grid; grid-template-columns: 1fr 1px 1fr 1px 1fr; margin-right: 12px; margin-top: 12px; } .section-child { display: flex; justify-content: center; align-items: center; min-width: 0; background-color: green; } .child-title { /* white-space: nowrap; */ } .vertical-separator { background-color: rgba(0, 0, 0, 0.3); margin: 8px; } 
 <div class="top-level"> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title text text text text text text text text text text</h4> <!--A lot more content here--> </div> </section> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title text text text text text text</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="vertical-separator"></div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> </div> 

Here's how it works:

Flexbox is not the perfect choice for table like layout, but you can get close though:

  • add flex: 1 1 100% to sectionchild , and it will shrink (or grow) equally, based on being set to be 100%

  • add overflow: hidden , or min-width , to tell the section-child they are allowed to be smaller than their content

  • add flex-basis: 100% , or flex-grow: 1 , to section and it will take full with of its parent, the top-level

As vertical-separator , I instead used a pseudo ::after on every section-child but the first, and since it use absolute position, position: relative is needed on the section-child .

 .top-level { display: flex; flex-flow: row wrap; } .section { flex-basis: 100%; /* added */ display: flex; flex-flow: row nowrap; border: 1px solid; margin-right: 12px; margin-top: 12px; } .section-child { position: relative; /* added */ display: flex; flex-flow: column nowrap; align-items: center; flex: 1 1 100%; /* added */ overflow: hidden; /* added */ } .child-title { white-space: nowrap; } .section-child + .section-child::after { content: ''; position: absolute; left: 0; top: 10%; height: 80%; border-left: 1px solid rgba(0,0,0,0.3); } 
 <div class="top-level"> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> </div> 

Several times in your code, you wrote claas instead of class :

<div claas="section-child">
  <h4 class="child-title">Title</h4>
  <!--A lot more content here-->
</div>

Then you should simplify your html structure by removing the vertical-separator divs and using css borders instead:

 .top-level { display: flex; flex-flow: row wrap; } .section { display: flex; flex-flow: row nowrap; border: 1px solid; margin-right: 12px; margin-top: 12px; } .section-child { display: flex; flex-flow: column nowrap; align-items: center; flex: 1 1 0; } .section-child:not(:last-of-type) { margin: 8px 0; border-right: solid 1px rgba(0, 0, 0, 0.3); } .child-title { white-space: wrap; } 
 <div class="top-level"> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> <section class="section"> <div class="section-child"> <h4 class="child-title">Title</h4> <!--A lot more content here--> </div> <div class="section-child"> <h4 class="child-title">Longer title</h4> <!--A lot more content here--> </div> <div class="section-child"> <h4 class="child-title">Much much longer title</h4> <!--A lot more content here--> </div> </section> </div> 

I removed the white-space: nowrap for .child-title because flex values are just hints and without wrapping "Much much longer title" will take too much space. If you really want to use nowrap , you will have to ensure your container is large enough and maybe use overflow.

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