Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make flex items have equal width in a row

I want the headers (h4.child-title) to have the same length within the parent container in the below example.

But I'm not successful in achieving this.

.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>
like image 797
Ashok Koyi Avatar asked Jun 27 '17 10:06

Ashok Koyi


People also ask

How do you do equal width on flex?

EQUAL HEIGHT + WIDTH COLUMNS WITH MARGINSAdd display:flex, justify-content: space-between; to the parent and give a width to the boxes that totals to less than 100%. E.g. These boxes have a width of 32% each.

How do you align Flex items in a row?

By default items start from the left if flex-direction is row , and from the top if flex-direction is column . You can change this behavior using justify-content to change the horizontal alignment, and align-items to change the vertical alignment.

How do you fix the width of a flex item?

A flexbox item can be set to a fixed width by setting 3 CSS properties — flex-basis, flex-grow & flex-shrink. flex-basis : This property specifies the initial length of the flex item. flex-grow : This property specifies how much the flex item will grow relative to the rest of the flex items.


1 Answers

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:

  • Make flex-grow expand items based on their original size
  • Why doesn't flex item shrink past content size?

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:

  • Equal height rows in CSS Grid Layout
like image 80
Michael Benjamin Avatar answered Oct 16 '22 00:10

Michael Benjamin