Managing CSS Flex-Box Growth in Multi-Line to Create a Grid of Equal Blocks

Managing CSS flex-box growth in multi-line to create a grid of equal blocks

This is totally possible, however, you have to know how many columns you'll have at a maximum. http://jsfiddle.net/kelunik/C2q8D/6/

Solution

By adding a few empty placeholders, your cards get equally sized. You just have to make sure, you're adding enough placeholders. It doesn't matter if there are too many, because they'll have a height of zero and are not visible.

CSS

section {
display: flex;
flex-flow: row wrap;
background-color: blue;
}

div {
background-color: red;
height: 3rem;
flex: 1 0 10rem;
}

div:nth-child(even) {
background-color: green;
}

div:empty {
margin: 0;
height: 0;
border: 0;
background: transparent;
}

HTML

<section>
<div>a</div>
<div>b</div>
<div>c</div>
<div>d</div>
<div>e</div>
<div>f</div>
<div>g</div>
<div>h</div>
<div>i</div>
<div>j</div>
<div>k</div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</section>

Group of items with responsive equal width in multi-line context, issue with last-line

Found a solution:

Simply add as many "empty" items as you expect the maximum on a line to be (a few more don't hurt but have at least enough for a full line) and then add the two bits relating to div:empty from the CSS below.

CSS

nav {
margin: 20px 0px;
}
nav #linkgroup {
display: flex;
flex-wrap: wrap;
justify-content: flex-start; /* aligns left when not full */
align-items: center;
align-content: space-around;
}
nav #linkgroup .link {
min-width: 120px;
width: 120px; /* only used because of Safari issue below */
max-width: 160px;
height: 30px;
margin: 5px;
flex-grow: 1;
flex-basis: auto; /* 0 gives all exact same size but have to use auto and set 'width' for Safari issue https://bugs.webkit.org/show_bug.cgi?id=136041 */
line-height: 30px; /* set equal to height, for vertical align trick */
text-align: center;
}
nav #linkgroup .link a.btn {
display: block;
vertical-align: middle;
line-height: normal;
border-radius: 2px;
padding: 5px 10px 5px 10px;
border: solid #1f628d 2px;
text-decoration: none;
}
#linkgroup > div:empty {
height: 0; /* I think visibility: hidden; would do the same */
}
@media only screen
and (min-width: 1030px) {
#linkgroup > div:empty {
display: none;
}
}

HTML

  <nav>
<div id="linkgroup">
<div class="link"><a class="btn" href="#">A</a></div>
<div class="link"><a class="btn" href="#">AB</a></div>
<div class="link"><a class="btn" href="#">ABC</a></div>
<div class="link"><a class="btn" href="#">ABCD</a></div>
<div class="link"><a class="btn" href="#">ABCDE</a></div>
<div class="link"><a class="btn" href="#">ABCDEF</a></div>
<div class="link"><a class="btn" href="#">ABCDEFG</a></div>
<div class="link"></div>
<div class="link"></div>
<div class="link"></div>
<div class="link"></div>
<div class="link"></div>
<div class="link"></div>
</div>
</nav>

How can I allow flex-items to grow while keeping the same size?

This is something that cannot be expressed via CSS Flexbox right now. Someone asked basically this exact question on the CSS Working Group Mailing List a few days ago, and the response was: "At the moment, no, this is not possible. This is a high-priority item for Flexbox 2, though.

You may be able to hack up something like you want using max-width, though -- that'll prevent flex items (particularly those on the last line) from growing indefinitely. Here's a forked version of your plunk with a nonzero flex-grow, and with max-width: 10em.

(I chose 10em arbitrarily; you could also use e.g. max-width: calc(100%/5), if you want to make sure each flex item takes up no more than 1/5 of the line, for example.)

Better way to set distance between flexbox items

  • Flexbox doesn't have collapsing margins.
  • Flexbox doesn't have anything akin to border-spacing for tables (edit: CSS property gap fulfills this role in newer browsers, Can I use)

Therefore achieving what you are asking for is a bit more difficult.

In my experience, the "cleanest" way that doesn't use :first-child/:last-child and works without any modification on flex-wrap:wrap is to set padding:5px on the container and margin:5px on the children. That will produce a 10px gap between each child and between each child and their parent.

Demo

.upper {
margin: 30px;
display: flex;
flex-direction: row;
width: 300px;
height: 80px;
border: 1px red solid;

padding: 5px; /* this */
}

.upper > div {
flex: 1 1 auto;
border: 1px red solid;
text-align: center;

margin: 5px; /* and that, will result in a 10px gap */
}

.upper.mc /* multicol test */ {
flex-direction: column;
flex-wrap: wrap;
width: 200px;
height: 200px;
}
<div class="upper">
<div>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa<br/>aaa</div>
<div>aaa<br/>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa</div>
</div>

<div class="upper mc">
<div>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa<br/>aaa</div>
<div>aaa<br/>aaa<br/>aaa</div>
<div>aaa</div>
<div>aaa</div>
</div>

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>

CSS - Equal Height Columns?

Grid

Nowadays, I prefer grid because it allows keeping all layout declarations on parent and gives you equal width columns by default:

.row {  display: grid;  grid-auto-flow: column;  gap: 5%;}
.col { border: solid;}
<div class="row">  <div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>  <div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam.</div>  <div class="col">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo.</div></div>

Applying an ellipsis to multiline text

I finally found a solution to do what I want.
As p a paragraphe and article the wrapper.
If you want to apply ellipsis to p depending on article height (which also depends on window height), you need to get the height of the article, the line-height of the p and then articleHeight/lineHeight to find the number of line-clamp that can be added dynamically then.

The only thing is the line-height should be declared in the css file.

Check the following code. If you change the height of the window, the line-clamp will change. Can be great to create a plug-in aiming to do that.

jsfiddle

function lineclamp() {  var lineheight = parseFloat($('p').css('line-height'));  var articleheight = $('article').height();   var calc = parseInt(articleheight/lineheight);  $("p").css({"-webkit-line-clamp": "" + calc + ""});}

$(document).ready(function() { lineclamp();});
$( window ).resize(function() { lineclamp();});
article {  height:60%;  background:red;  position:absolute;}
p { margin:0; line-height:120%; display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><article> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque lorem ligula, lacinia a justo sed, porttitor vulputate risus. In non feugiat risus. Sed vitae urna nisl. Duis suscipit volutpat sollicitudin. Donec ac massa elementum massa condimentum mollis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla sollicitudin sapien at enim sodales dapibus. Pellentesque sed nisl eu sem aliquam tempus nec ut leo. Quisque rutrum nulla nec aliquam placerat. Fusce a massa ut sem egestas imperdiet. Sed sollicitudin id dolor egestas malesuada. Quisque placerat lobortis ante, id ultrices ipsum hendrerit nec. Quisque quis ultrices erat.Nulla gravida ipsum nec sapien pellentesque pharetra. Suspendisse egestas aliquam nunc vel egestas. Nullam scelerisque purus interdum lectus consectetur mattis. Aliquam nunc erat, accumsan ut posuere eu, vehicula consequat ipsum. Fusce vel ex quis sem tristique imperdiet vel in mi. Cras leo orci, fermentum vitae volutpat vitae, convallis semper libero. Phasellus a volutpat diam. Ut pulvinar purus felis, eu vehicula enim aliquet vitae. Suspendisse quis lorem facilisis ante interdum euismod et vitae risus. Vestibulum varius nulla et enim malesuada fringilla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque lorem ligula, lacinia a justo sed, porttitor vulputate risus. In non feugiat risus. Sed vitae urna nisl. Duis suscipit volutpat sollicitudin. Donec ac massa elementum massa condimentum mollis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nulla sollicitudin sapien at enim sodales dapibus. Pellentesque sed nisl eu sem aliquam tempus nec ut leo. Quisque rutrum nulla nec aliquam placerat. Fusce a massa ut sem egestas imperdiet. Sed sollicitudin id dolor egestas malesuada. Quisque placerat lobortis ante, id ultrices ipsum hendrerit nec.</p></article>

Fluid width with equally spaced DIVs

See: http://jsfiddle.net/thirtydot/EDp8R/

  • This works in IE6+ and all modern browsers!
  • I've halved your requested dimensions just to make it easier to work with.
  • text-align: justify combined with .stretch is what's handling the positioning.
  • display:inline-block; *display:inline; zoom:1 fixes inline-block for IE6/7, see here.
  • font-size: 0; line-height: 0 fixes a minor issue in IE6.

#container {  border: 2px dashed #444;  height: 125px;  text-align: justify;  -ms-text-justify: distribute-all-lines;  text-justify: distribute-all-lines;  /* just for demo */  min-width: 612px;}
.box1,.box2,.box3,.box4 { width: 150px; height: 125px; vertical-align: top; display: inline-block; *display: inline; zoom: 1}
.stretch { width: 100%; display: inline-block; font-size: 0; line-height: 0}
.box1,.box3 { background: #ccc}
.box2,.box4 { background: #0ff}
<div id="container">  <div class="box1"></div>  <div class="box2"></div>  <div class="box3"></div>  <div class="box4"></div>  <span class="stretch"></span></div>


Related Topics



Leave a reply



Submit