Equal width flex items even after they wrap
Currently, flexbox offers no clean solution for aligning flexible items in the last row or column. It's beyond the scope of the current spec.
Here's more information and various solutions people have used to get around the problem:
- Targeting flex items on the last row
- Is it possible for flex items to align tightly to the items above them?
However, last-row alignment is not a problem with another CSS3 technology, Grid Layout. In fact, it's very simple with this method (and requires no changes to the HTML):
.container { display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); grid-auto-rows: 20px; grid-gap: 5px;}
.item { background: yellow; text-align: center; border: 1px solid red;}
<div class="container"> <div class="item">1</div> <div class="item">2</div> <div class="item">3</div> <div class="item">4</div> <div class="item">5</div> <div class="item">6</div> <div class="item">7</div> <div class="item">8</div> <div class="item">9</div> <div class="item">10</div></div>
How to keep wrapped flex-items the same width as the elements on the previous row?
TL;DR
This is not something I'd call a solution per se, but it's a rather elegant workaround that only uses media queries, and more importantly no JavaScript!
Mixin (SCSS):
@mixin flex-wrap-fix($flex-basis, $max-viewport-width: 2000px) {
flex-grow: 1;
flex-basis: $flex-basis;
max-width: 100%;
$multiplier: 1;
$current-width: 0px;
@while $current-width < $max-viewport-width {
$current-width: $current-width + $flex-basis;
$multiplier: $multiplier + 1;
@media(min-width: $flex-basis * $multiplier) {
max-width: percentage(1/$multiplier);
}
}
}
Usage:
Apply the mixin to your flex item:
.flex-item {
@include flex-wrap-fix(100px)
}
Update:
The above mixin should do the trick, as long as you your flex container width matches your viewport size, as is the case in OP's example. Media queries won't help you otherwise, because they're always based on the viewport width. However, you could use the css-element-queries
library and its element queries instead of browser media queries. Here's a mixin that you can apply to the flex container:
@mixin flex-container-wrap-items($flex-basis, $max-expected-width: 2000px) {
display: flex;
flex-wrap: wrap;
> * {
max-width: 100%;
flex-grow: 1;
flex-basis: $flex-basis;
}
$multiplier: 1;
$current-width: 0px;
@while $current-width < $max-expected-width {
$current-width: $current-width + $flex-basis;
$multiplier: $multiplier + 1;
&[min-width~="#{$flex-basis * $multiplier}"] > * {
max-width: percentage(1/$multiplier);
}
}
}
Explanation:
Let's say, as per the OP's example, we want each item to have a maximum width of 100px
, so we know that for a browser width of 100px
we can fit one item per row, and so on:
| Viewport Width | Max Item Count Per Row | Item Width (min-max) |
|----------------|------------------------|----------------------|
| <= 100 | 1 | 0px - 100px |
| <= 200 | 2 | 50px - 100px |
| <= 300 | 3 | 50px - 100px |
| <= 400 | 4 | 50px - 100px |
| <= 500 | 5 | 50px - 100px |
| <= 600 | 6 | 50px - 100px |
We can write media queries to create the following rules:
| Viewport Width | Max Item Count Per Row | Item Max Width | Calculation |
|------------------------------------------------------------------------|
| <= 100px | 1 | 100% | (100/1) |
| <= 200px | 2 | 50% | (100/2) |
| <= 300px | 3 | 33.33333% | (100/3) |
| <= 400px | 4 | 25% | (100/4) |
| <= 500px | 5 | 20% | (100/5) |
| <= 600px | 6 | 16.66666% | (100/6) |
Like this:
li {
flex: 1 0 0
max-width: 100%;
}
@media(min-width: 200px) {
li { max-width: 50%; }
}
@media(min-width: 300px) {
li { max-width: 33.33333%; }
}
@media(min-width: 400px) {
li { max-width: 25%; }
}
@media(min-width: 500px) {
li { max-width: 20%; }
}
@media(min-width: 600px) {
li { max-width: 16.66666%; }
}
Of course, that's repetitive, but most likely you're using some sort of preprocessor, which can take care of the repetitiveness for you. That's precisely what the mixin in the above TL;DR section does.
All we have to do now is to specify 100px
as our flex-basis
, and optionally the maximum browser window width (defaults to 2000px
) to create the media queries for:
@include flex-wrap-fix(100px)
Example
Finally, a forked version of the original CodePen example with the desired output, using the above mixin:
http://codepen.io/anon/pen/aNVzoJ
equal width flex items
The problem you're having is mostly the third item on the second row.
An initial setting on flex items is min-width: auto
, which means the item will have a minimum width based on its content. This could be a fixed-width element or, in your case, the longest word.
Since your content in that item has one long string of text with no space characters, it's forcing the item to expand, throwing off the column alignments.
Simply use a space character to break that string of text and the issue is resolved.
I would also set the item widths to 20% and override the min-width: auto
default for more stability.
More details here: Why doesn't flex item shrink past content size?
* { box-sizing: border-box;}
.container { display: flex; flex-direction: column; text-align: center;}
.first,.second { display: flex; /* flex-wrap: wrap; <-- removed for demo */}
p { padding: 1em .5em; flex: 0 0 20%; /* adjustment */ overflow: hidden; /* adjustment */ border: 1px dashed green;}
p::before { content: '✔';}
<div class="container"> <div class="first"> <p> Lorem ipsum dolor sit amet imsppmfmmfmfmfmfmfmfm</p> <p> Lorem ipsum dolor sit ametlorem lorem lorem lorem lorem lorem, </p> <p> Lorem ipsum dolor sit amet,</p> <p> Lorem ipsum dolor sit amet, lorem ipsum</p> <p> Lorem ipsum dolor sit amet,</p> </div> <div class="second"> <p> Lorem ipsum dolor sit amet,</p> <p> Lorem ipsum dolor sit amet,</p> <p> Lorem ipsum dolor sit amet, jkdasnjdcmx,cnc,mncn,mn,mcmn</p> <p> Lorem ipsum dolor sit amet, </p> <p> Lorem ipsum dolor sit amet,dddddd </p> </div></div>
Equal size of flex item while breaking the last item to next line
You should set flex-grow:0
and should be calc(100% / 6)
instead of calc(100% / 7)
. Also I added box-sizing:border-box;
for borders to be included in width.
ul { padding: 0; margin: 0; list-style-type: none; display: flex; flex-flow: row wrap;}
li { flex: 1; border: solid 1px; text-align: center; flex-basis: calc(100% / 6); box-sizing: border-box;}
.keep-next-line { flex-grow: 0;}
<ul> <li>1</li> <li>2</li> <li>3</li> <li>4</li> <li>5</li> <li>6</li> <li class="keep-next-line">7</li> <!--Kepp this next line, but size should be equal to other item--></ul>
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;
Flex: wrapped items with same width as the rest
Add a few extra flex items and make them "invisible" by setting their height/padding/border to 0/none.
Based on how many columns you'll need, it takes one less for it to work.
* { box-sizing: border-box;}
.wrapper { border: 1px solid red; width: 100%; max-width: 800px;}
ul { list-style: none; margin: 0; padding: 0;
display: flex; flex-wrap: wrap; margin: -1em -1em 0 0;}
li { border: 1px solid black; padding: 1em; margin: 1em 1em 0 0; flex: 1 1 10em;}
li:nth-last-child(-n+3) { height: 0; border: none; padding: 0; margin: 0 1em 0 0;}
<!DOCTYPE html><html>
<head> <link rel="stylesheet" href="style.css"> <script src="script.js"></script> </head>
<body> <div class="wrapper"> <ul> <li>Item 1</li> <li>Item 2</li> <li>Item 3</li> <li>Item 4</li> <li>Item 5</li> <li>Item 6</li> <li>Item 7</li> <li>Item 8</li> <li></li> <li></li> <li></li> </ul> </div> </body>
</html>
My 25% width flex item is taking 100% width after wrapping
You have the items set to flex: 1 0 25%
.
This breaks down to:
flex-grow: 1
flex-shrink: 0
flex-basis: 25%
Remove flex-grow: 1
. It's telling the items to consume free space.
Try this: flex: 0 0 25%
For more details and other options, see these posts:
- Equal width flex items even after they wrap
- Flexbox: 4 items per row
Flex-wrap with equal width
You can use map()
and get()
to return array of widths and then with Math.max
you can find maximum value in that array and apply it as width on each item
var w = $('.narrow > div').map(function() { return $(this).width();}).get();
var max = Math.max.apply(null, w);$('.narrow > div').width(max);
.wrap { width: 300px; background: #fff;}.narrow { display: flex; flex-wrap: wrap;}.narrow >* { background: #ccc; border: 2px solid #fff; padding: 10px; color: #fff;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div class="wrap"> <div class="narrow"> <div class="item1"> Longest sentence. </div> <div class="item2"> Short text. </div> <div class="item3"> Another text. </div> <div class="item1"> Longest sentence. </div> <div class="item2"> Short text. </div> <div class="item3"> Another text. </div> </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:
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 applyflex: 1
to.section
, as well.A flex item cannot be smaller than the size of its content, by default. The initial setting is
min-width: auto
. Soflex: 1
cannot work to equally distribute container space, because a flex item cannot shrink past the longest item. You need to override this behavior withmin-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>
Related Topics
How Do Search Engines Deal With Angularjs Applications
Html Encoding Issues - "Â" Character Showing Up Instead of "&Nbsp;"
How to Force a Web Browser Not to Cache Images
How to Add an HTML Link in the Body of a Mailto Link
Invert CSS Font-Color Depending on Background-Color
Bootstrap 4: Multilevel Dropdown Inside Navigation
How to Wrap Text Around an Image Using Html/Css
What's the Difference Between ≪B≫ and ≪Strong≫, ≪I≫ and ≪Em≫
Html5 Canvas Drawimage: How to Apply Antialiasing
Does Opacity:0 Have Exactly the Same Effect as Visibility:Hidden
What Is the Correct Value For the Disabled Attribute
When to Use the !Important Property in Css
How to Center Text Vertically With a Large Font-Awesome Icon
The Reference to Entity "Foo" Must End With the ';' Delimiter