Willege Willege - 7 months ago 58
HTML Question

Absolute positioning in flexbox

I have a flex container (the blue square) with the following properties:

display: flex;
justify-content: center;
align-items: center;
flex-wrap: nowrap;


Therefore, its children (the light blue squares) arrange themselves as you see below. However, I'd like to add another child (the green square) out of the normal flow and position it relative to its parent. To position it as you see below, I'd ideally write something like
bottom: 20px;
and
margin: auto;
.

enter image description here

I tried to play around with
z-index
to no avail. How should I approach this? Should I resort to creating another parent element?

Answer

Method #1: CSS Positioning Properties

Apply position: relative to the flex container.

Apply position: absolute to the green square.

Now the green square is absolutely positioned within the bounds of the nearest positioned ancestor. In other words, the green square is removed from the normal flow but stays within the flex container.

Use the offset properties top, bottom, left and right to move the green square around.

flex-container {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-wrap: nowrap;
    position: relative;
    border: 4px solid blue;
    height: 300px;
    width: 300px;
}

flex-container > flex-item:first-child {
    display: flex;
}

flex-container > flex-item:first-child > flex-item {
    border: 4px solid aqua;
    height: 50px;
    width: 50px;
    margin: 0 5px;
}

flex-container > flex-item:last-child {
    position: absolute;
    bottom: 40px;
    left: 50%;
    transform: translateX(-50%); /* fine tune horizontal centering */
    border: 4px solid chartreuse;
    height: 50px;
    width: 50px;
}
<flex-container>

    <flex-item><!-- also flex container -->

	    <flex-item></flex-item>

	    <flex-item></flex-item>
        
	    <flex-item></flex-item>

    </flex-item>
    
    <flex-item></flex-item>

</flex-container>


Method #2: Flex Auto Margins & Invisible Flex Item

With a combination of auto margins and a new, invisible flex item the layout can be achieved.

The new flex item is identical to the bottom item and is placed at the opposite end (the top). It's added for equal balance.

More specifically, because flex alignment is based on the distribution of free space, the new item is necessary to keep the three blue boxes vertically centered. The new item must be the exact same height as the existing green item, or the blue boxes wouldn't be precisely centered.

The new item is removed from view with visibility: hidden.

flex-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    border: 4px solid blue;
    height: 300px;
    width: 300px;
}

flex-container > flex-item:first-child {
    margin-top: auto;
    visibility: hidden;
}

flex-container > flex-item:nth-child(2) {
    margin-top: auto;
    display: flex;
}

flex-container > flex-item:last-child {
    margin-top: auto;
    margin-bottom: auto;
}

flex-container > flex-item:first-child,
flex-container > flex-item:last-child {
    border: 4px solid chartreuse;
    height: 50px;
    width: 50px;
}

flex-container > flex-item:nth-child(2) > flex-item {
    border: 4px solid aqua;
    height: 50px;
    width: 50px;
    margin: 0 5px;
}
<flex-container>

    <flex-item></flex-item>

    <flex-item><!-- also flex container -->

	    <flex-item></flex-item>

	    <flex-item></flex-item>
        
	    <flex-item></flex-item>

    </flex-item>
    
    <flex-item></flex-item>

</flex-container>