Jessica Jessica - 5 months ago 17
HTML Question

Flex items not wrapping in column-direction flexbox

I have an

outerWrapper
,
innerWrapper
, and children.
outerWrapper
has a height of
300px
, and is
display: flex
.
innerWrapper
is also
display: flex
, and is
flex-direction: column
.

When I add
align-items
with a value of anything but
stretch
to
outerWrapper
, the children display one long column. They ignore the
300px
height. Here's an image of how it displays:

enter image description here

It should display like this:

enter image description here

Just with
align-items: flex-end
.

Why is this happening, and how can I use
align-items: flex-end
and have the children display like the second image?

JSFiddle





#outerWrapper {
height: 300px;
background-color: lightgreen;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: flex-end;
}
ul {
padding: 0;
margin: 0;
display: flex;
align-items: center;
flex-wrap: wrap;
flex-direction: column;
}
li {
list-style-type: none;
width: 100px;
height: 100px;
background-color: lightblue;
border: 1px solid;
}

<div id="outerWrapper">
<ul id="innerWrapper">
<li class="child">I'm #01</li>
<li class="child">I'm #02</li>
<li class="child">I'm #03</li>
<li class="child">I'm #04</li>
<li class="child">I'm #05</li>
</ul>
</div>





Update

The answer to this question, is to add a height of
210px
to
innerWrapper
. But I need to get to that number using JavaScript, because the amount of boxes will be dynamic.

I tried the following code:

innerWrapper.style.height = (lastChild.offsetTop - innerWrapper.offsetTop + lastChild.offsetHeight) + 'px';


but it didn't fix it. It just made the height to: 5 * 102 (5 = number of boxes; 102 = height + border).

How can I set the correct height to
innerWrapper
using JavaScript? (I can't do height: 100% because I won't be able to set align-items: flex-end or center.)

JSFiddle





var innerWrapper = document.getElementById('innerWrapper');
var lastChild = innerWrapper.lastElementChild;
newHight = lastChild.offsetTop - innerWrapper.offsetTop + lastChild.offsetHeight;
innerWrapper.style.height = newHight + 'px';

#outerWrapper {
height: 300px;
background-color: lightgreen;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: flex-end;
}
ul {
padding: 0;
margin: 0;
display: flex;
align-items: center;
flex-wrap: wrap;
flex-direction: column;
/*height: 206px;*/
}
li {
list-style-type: none;
width: 100px;
height: 100px;
background-color: lightblue;
border: 1px solid;
}

<div id="outerWrapper">
<ul id="innerWrapper">
<li class="child">I'm #01</li>
<li class="child">I'm #02</li>
<li class="child">I'm #03</li>
<li class="child">I'm #04</li>
<li class="child">I'm #05</li>
</ul>
</div>




Answer

You've defined a height for #outerWrapper: height: 300px.

Just give the child – #innerWrapper – an equal height: height: 100%. Now they wrap.

Then, if you want the items positioned at the container bottom, use flex auto margins on the odd-numbered items.

Use an invisible pseudo-element to make the last odd-numbered item always align with the top row.

#outerWrapper {
    height: 300px;
    background-color: lightgreen;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: flex-end;
}

ul {
    padding: 0;
    margin: 0;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    flex-direction: column;
    height: 100%;                           /* NEW */
}

li {
    list-style-type: none;
    width: 100px;
    height: 100px;
    background-color: lightblue;
    border: 1px solid;
}

li:nth-child(odd) { margin-top: auto; }      /* NEW */

ul::after {
    content: "";                              /* NEW */
    width: 100px;                             /* NEW */
    height: 100px;                            /* NEW */
    border: 1px solid;                        /* NEW */
    visibility: hidden;                       /* NEW */
}
<div id="outerWrapper">
    <ul id="innerWrapper">
        <li class="child">I'm #01</li>
        <li class="child">I'm #02</li>
        <li class="child">I'm #03</li>
        <li class="child">I'm #04</li>
        <li class="child">I'm #05</li>
    </ul>
</div>

Revised Fiddle

Comments