Flexbox Not Giving Equal Width to Elements

Flexbox not giving equal width to elements

There is an important bit that is not mentioned in the article to which you linked and that is flex-basis. By default flex-basis is auto.

From the spec:

If the specified flex-basis is auto, the used flex basis is the value of the flex item’s main size property. (This can itself be the keyword auto, which sizes the flex item based on its contents.)

Each flex item has a flex-basis which is sort of like its initial size. Then from there, any remaining free space is distributed proportionally (based on flex-grow) among the items. With auto, that basis is the contents size (or defined size with width, etc.). As a result, items with bigger text within are being given more space overall in your example.

If you want your elements to be completely even, you can set flex-basis: 0. This will set the flex basis to 0 and then any remaining space (which will be all space since all basises are 0) will be proportionally distributed based on flex-grow.

li {
flex-grow: 1;
flex-basis: 0;
/* ... */
}

This diagram from the spec does a pretty good job of illustrating the point.

And here is a working example with your fiddle.

Flexbox items do not have equal widths despite flex-basis: 0

If you don't specify a width the flex container is just doing it's job and growing as specified. A solution to this is to set the min-width so there is no implicit width.

Additionally here is some valuable information on flex-basis: MDN

In case both flex-basis (other than auto) and width (or height in case of flex-direction: column) are set for an element, flex-basis has priority.

.items {    display: flex;    justify-content: space-between;}
.item { flex: 1 0 0; border: 1px solid #333; background: #fde669; min-width: 0;}
.item-title { font-size: 25px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;}
<div class="items">  <div class="item">    <div class="item-title">Title 1</div>  </div>  <div class="item">    <div class="item-title">Title 2</div>  </div>  <div class="item">    <div class="item-title">Some very long title</div>  </div>  <div class="item">    <div class="item-title">Title 3</div>  </div>  </div>

Maintain equal width on flexbox columns when adding a margin

Maybe flex-basis can help:

body {  margin: 0;}
html { box-sizing: border-box;}
.grid { display: flex;}
.column {
display: flex; flex-direction: column; justify-content: center;}
.one { flex-basis: 50%}
.two { flex: 1; margin: 0 10vw;}
img { display: block; /* Site wide to make images responsive */ max-width: 100%; height: auto; /* Cover column */ width: 100%; height: 100%; object-fit: cover; object-position: right center;}
h2 { margin: 0 0 24px;}
p { margin: 0 0 24px;}
a,a:hover,a:visited,a:focus { color: #000;}
<div class="grid">  <div class="column one">    <img src="https://hackernoon.com/hn-images/1*mONNI1lG9VuiqovpnYqicA.jpeg" alt="Bad Ass Cat">  </div>    <div class="column two">
<h2>Here's a Heading</h2> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum aliquam ut ex at fermentum. Proin nec eros at elit mollis porttitor. Vivamus vestibulum luctus metus, ac gravida felis varius nec. Praesent non mauris et tortor lacinia cursus quis at turpis. Nullam scelerisque vitae leo nec convallis. Proin volutpat, est non iaculis facilisis, tellus tortor pulvinar lectus, eu porttitor diam dui eget enim. Praesent non ipsum dui.</p> <a href="#">Click Me</a>
</div></div>

Make flex items have equal width in a row

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>

How to place items in flexbox take equal width?

I moved flex-grow: 1 from where you placed it, because it wasn't doing anything. This is a rule that affects flex children. Therefore, I moved it to affect all direct children of the flex parent, .wrapper.

.wrapper {
display: flex;
/* flex-grow: 1; <-- moved below */

& > * {
flex-grow: 1;
}
}

Sample Image

jsFiddle

How to make flexbox items the same size?

Set them so that their flex-basis is 0 (so all elements have the same starting point), and allow them to grow:

flex: 1 1 0px

Your IDE or linter might mention that the unit of measure 'px' is redundant. If you leave it out (like: flex: 1 1 0), IE will not render this correctly. So the px is required to support Internet Explorer, as mentioned in the comments by @fabb;

unable to display elements of same width and height correctly with flexbox

The intrinsic widths of your images are smaller than their containing blocks. Add the following declarations to your image selector:

img {
width: 100%; /* ensure width is equal to containing block's content area */
display: block; /* remove any white-space */
}

Flexbox - How to split row 50/50 between two elements and wrap if width falls below min-width?

Just change width: 45% to flex-grow: 1, the flex items will try to take up the whole row. flex-basis controls how large they are in relation to eachother, by default they will attempt to stay the same size. Currently they wrap at 332px because of the 16px of padding.

mat-card {
margin: 10px;
min-width: 300px;
flex-grow: 1;
}


Related Topics



Leave a reply



Submit