How to align left last row/line in multiple line flexbox [duplicate]
Asked Answered
T

6

98

I have a major issue with flexbox layout. I build a container with a boxes filled with images, and i decided to use flexbox layout to justify the content to make it looks like a grid

Her's the code:

<div class="container">

    <div class="item"></div>
    <div class="item"></div>
    ...
    <div class="item"></div>

</div>

and the CSS:

.container {
    display: flex;
    display: -webkit-flex;
    display: -moz-flex;
    justify-content: space-around;
    -webkit-justify-content: space-around;
    -moz-justify-content: space-around;
    flex-flow: row wrap;
    -webkit-flex-flow: row wrap;
    -moz-flex-flow: row wrap;
}

.container .item { width: 130px; height: 180px; background: red; margin: 0 1% 24px; }

And everything looks good except the last line/row - when it not contain the same number of element that other lines, centering elements and it broke my grid effect.

http://jsfiddle.net/puz219/7Hq2E/

How to align last line/row to left side?

Teddi answered 4/5, 2013 at 19:11 Comment(7)
I removed the Flex tag as this has nothing to do with the Adobe/Apache UI framework.Venetis
Even if you could adjust the contents of only the last line, there's no way you could line up your elements because of space-around. The best you can do is use space-between instead: jsfiddle.net/7Hq2E/1. Also, there is no moz prefix on the standard properties. They should be replaced with properties for IE10: gist.github.com/cimmanon/727c9d558b374d27c5b6Baloney
Just remove justify-content from your code and it will work. You can fine tune the space between flex items with the margin property. http://jsfiddle.net/katranci/kkRmW/Tabb
I know this is old, but the comment katranci left is incorrect. If you don't justify the content, gaps develop on the right when resizing. Try resizing the width of each fiddle and watch the right side. You'll notice there is a HUGE difference.Lifesaving
Check this out: https://mcmap.net/q/37399/-flex-box-align-last-row-to-gridFrausto
All you need is a preprocessor mixin, and a single line of code to use that mixin. See here: https://mcmap.net/q/37546/-how-to-keep-wrapped-flex-items-the-same-width-as-the-elements-on-the-previous-rowDeplete
I don't know where to put this comment, and it has nothing to do with the answer, so skip as needed. But how can this question be marked as "already been answered" and flagged as a duplicate when it was asked over a year before the linked answer was posted?Longlegged
R
131

Got it. (I think)(this is my first contribution here!)

Imagine a layout which needs to have 4 images per row. w:205 h:174 Problem: Using justify-content:space-around, if the last row doesn´t have 4 images (has 3, 2 or 1), they would not respect the grid, they would spread. So.

Create in the html 3 divs with the class "filling-empty-space-childs" like this.

.filling-empty-space-childs {
    width:205px; /*the width of the images in this example*/
    height:0; /*Important! for the divs to collapse should they fall in a new row*/
}

The flexbox container has display:flex / flex-wrap:wrap; / justify-content:space-around

The last row can have 4, 3, 2, 1 images. 4 images: no problem, this three divs would collapse in a new row since they have no height. 3 images: no problem, one div is going to be in the same row, invisible, and the other two would wrap to a new row, but will collapse since they have no height. 2 images: no problem, two divs are going to be in the same row, invisibles, the rest... collapsed 1 image: no problem, the three divs are going to fill in the space.

Renae answered 17/7, 2015 at 14:19 Comment(13)
Hacky but genius. If using React, the extra (n - 1) filler divs can be well encapsulated in a wrapper component.Northumbria
wow, really nice. This solution can be mixed with :after if you need 2 columns only. And it's also work with variable column number depending on screen size. Amazing!Aport
Genius answer! I would say even add more empty child than (n-1) still works well!Facilitation
Here is a modification of the original jsFiddle that use this hack: jsfiddle.net/7Hq2E/172Deepset
This answer is the best. Not only it gives the solution - add as many empty containers as could ever be needed to fill the entire remaining with of the last row - and explains why it works - because even if there are less spaces than empty containers and they get moved to the next row, the next row still has height: 0 and layout doesn't change. Clever.Gracchus
Where this falls down is if you have a small number of items but a large containing box. The filler images will end up on the first line, thus not allowing the actual images to be centered on the first line. Nonetheless, if that's not a big deal to you, this works nicely.Backdate
@Aport I found the :after solution too, and it works with 3 columns as well, if you use justify-content: space-between;Solfa
You are a genius manAbsentminded
Diabolic! Genius! I 💙 U MAN!Dittman
Nice hack! Not the cleanest solution but considering flexbox limitations, this worked just fine for me. ThanksTranscendentalistic
{(new Array(emptyItemLen)).map( (_, idx) => (<div key={idx}></div>))}Misinform
Cleanest hack! Absolute genius.Accelerando
Impressed! Although handcrafted, it serves the purpose. Bravo!Apostate
B
54

Unfortunately this is not possible with flexbox.

The best work-around is to add invisible children 'filling up' the empty 'blocks' in the last row. That way, the actual, visible, element is aligned left.

Similar question: Flex-box: Align last row to grid

Benil answered 22/10, 2014 at 9:55 Comment(5)
Concise. This should be the accepted answer.Naresh
I came up with a CSS only solution.. the caveat being it can only ever account for two missing items, so will only work safely in a flex grid with a maximum of three items per wrapping row. Demo: codepen.io/lukejacksonn/pen/dozqVq The principle here is to use pseudo elements as the "invisible children" and give them the same flex property as the items in the container.Atrium
And here is a well explained work around for that: css-tricks.com/filling-space-last-row-flexboxBenzoyl
@WaleedAsender No, that's to fill the space. He wants to left-align the last row to the same columns of the previous rows. It's probably the most-wanted missing feature of flexbox.Abner
Excellent answer and I voted it up, but I don't think it should be marked as the accepted answer. I don't think there's any way to know how many invisible children to add because it changes with the size of the browser window.Redtop
C
24

You can use margin-right:auto on the last-child flex item.

The problem here is that you will lose the space-between property on the left for this flex item.

Hope it helps!

Crenation answered 9/10, 2015 at 12:43 Comment(1)
That only works for single last row. If there are two or more, they will share space and each will align right in that space.Oregon
K
9

I thought this example might be useful for anyone who wanted multiple items and allow for responsiveness, the grid items change depending on the viewport size. It does not use any invisible children, it's all done through css.

Might help someone trying align items to the left when the last row has less items and they require the page to be responsive.

http://codepen.io/kunji/pen/yNPVVb

Sample HTML

<div class="main-container">

    <div class="main-items-container">

        <div class="item-container">
          <h2>Item Name</h2>
        </div>

        <div class="item-container">
          <h2>Item Name</h2>
        </div>

        <div class="item-container">
          <h2>Item Name</h2>
        </div>

        <div class="item-container">
          <h2>Item Name</h2>
        </div>

        <div class="item-container">
          <h2>Item Name</h2>
        </div>

        <div class="item-container">
          <h2>Item Name</h2>
        </div>

    </div>

</div>

Sample CSS

.main-container {
  max-width: 1000px;
  min-width: 300px;
  margin: 0 auto;
  padding: 40px;
  box-sizing: border-box;
  border: 1px solid #000;
}

.main-items-container {
  display: -ms-flexbox;
  display: flexbox;
  display: -webkit-flex;
  display: -ms-flex;
  display: flex;
  padding: 0;
  margin: 10px 0;
  list-style: none;
  width: auto;
  -webkit-flex-flow: row wrap;
  justify-content: flex-start;
  -webkit-flex-wrap: wrap;
  flex-wrap: wrap;
  -webkit-align-items: stretch;
  align-items: stretch;
  box-sizing: border-box;
}

@media (min-width: 971px) {
  .item-container {
    margin: 10px 2%;
    width: 22%;
    padding: 10px;
    border: 1px solid #000;
    box-sizing: border-box;
  }
  .item-container:nth-child(4n+1) {
    margin-left: 0;
  }
  .item-container:nth-child(4n) {
    margin-right: 0;
  }
}

@media (min-width: 550px) and (max-width: 970px) {
  .item-container {
    margin: 10px 2.50%;
    width: 30%;
    padding: 10px;
    border: 1px solid #000;
    box-sizing: border-box;
  }
  .item-container:nth-child(3n+1) {
    margin-left: 0;
  }
  .item-container:nth-child(3n) {
    margin-right: 0;
  }
}

@media (max-width: 549px) {
  .item-container {
    margin: 10px 0;
    width: initial;
    padding: 10px;
    border: 1px solid #000;
    box-sizing: border-box;
  }
}
Karen answered 25/6, 2015 at 11:37 Comment(0)
R
2

This is not an effect you wanted to achieve?

http://jsfiddle.net/7Hq2E/21/

CSS:

.container {
    display: flex;
    display: -webkit-flex;
    display: -moz-flex;
    flex-flow: row wrap;
    -webkit-flex-flow: row wrap;
    -moz-flex-flow: row wrap;
}
.container .item {
    width: 23%;
    height: 180px;
    background: red;
    margin: 0 1% 20px;
}

HTML:

<div class="container">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
</div>
Romish answered 27/5, 2014 at 8:35 Comment(1)
This approach would only work if you wanted the same number of elements to be able to fit on each line, regardless of the size of the container. The asker is using absolute units (px). He wants a behavior like the picture thumbnails in Windows Explorer, where the space between each item adjusts, the last row is left aligned, and the number of items on each row changes according to the space available.Allograph
A
-2

I've checked it and it worked better in my HTML editor tool

the script should be the way

CSS Part

.container {
display: flex;
display: -webkit-flex;
display: -moz-flex;
justify-content: space-around;
-webkit-justify-content: space-around;
-moz-justify-content: space-around;
flex-flow: row wrap;
-webkit-flex-flow: row wrap;
-moz-flex-flow: row wrap;
}

.container .item { width: 130px; height: 180px; background: green; margin: 0 1% 24px; }

HTML Part

<div class="container">

    <div class="item"><a href='google.com'>Google</a></div>
    <div class="item"><a href='google.com'>Yahoo</a></div>
    <div class="item"><a href='google.com'>Bing</a></div>
</div>

<div class="container">
    <div class="item"><a href='google.com'>Google</a></div>
    <div class="item"><a href='google.com'>Yahoo</a></div>
    <div class="item"><a href='google.com'>Bing</a></div>

</div>


enter image description here

Ambsace answered 25/2, 2014 at 15:46 Comment(1)
It only shows as a single column on jsfiddle, though. It's also not clear from the picture if it centers upon resize. Judging by the two containers, it won't dynamically create fewer/more rows as the viewport shrinks/grows.Threat

© 2022 - 2024 — McMap. All rights reserved.