html - Center and bottom-align flex items -
i have flex container (the blue square) following properties:
display: flex; justify-content: center; align-items: center; flex-wrap: nowrap; therefore, children (the light blue squares) arrange see below. however, i'd add child (the green square) out of normal flow , position relative parent. position see below, i'd ideally write bottom: 20px; , margin: auto;.
i tried play around z-index no avail. how should approach this? should resort creating parent element?
below 5 options achieving layout:
- css positioning
- flexbox invisible dom element
- flexbox invisible pseudo-element
- flexbox
flex: 1 - css grid layout
method #1: css positioning properties
apply position: relative flex container.
apply position: absolute green flex item.
now green square absolutely positioned within flex container.
more specifically, green square removed document flow stays within bounds of nearest positioned ancestor.
use css offset properties top, bottom, left , right move 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><!-- flex container --> <flex-item></flex-item> <flex-item></flex-item> <flex-item></flex-item> </flex-item> <flex-item></flex-item> </flex-container> one caveat: browsers may not remove absolutely-positioned flex item normal flow. changes alignment in non-standard, unexpected way. more details: absolutely positioned flex item not removed normal flow in firefox & ie11
method #2: flex auto margins & invisible flex item (dom element)
with combination of auto margins , new, invisible flex item layout can achieved.
the new flex item identical bottom item , placed @ opposite end (the top).
more specifically, because flex alignment based on distribution of free space, new item necessary counterbalance keep 3 blue boxes vertically centered. new item must same height existing green item, or blue boxes won't precisely centered.
the new item removed view visibility: hidden.
in short:
- create duplicate of green box.
- place @ beginning of list.
- use flex
automargins keep blue boxes centered, both green boxes creating equal balance both ends. - apply
visibility: hiddenduplicate green box.
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><!-- flex container --> <flex-item></flex-item> <flex-item></flex-item> <flex-item></flex-item> </flex-item> <flex-item></flex-item> </flex-container> method #3: flex auto margins & invisible flex item (pseudo-element)
this method similar #2, except it's cleaner semantically , height of green box must known.
- create pseudo-element same height existing green box.
- place @ start of container
::before. - use flex
automargins keep blue boxes centered, green pseudo , dom elements creating equal balance both ends.
flex-container { display: flex; flex-direction: column; align-items: center; border: 4px solid blue; height: 300px; width: 300px; } flex-container::before { content: ""; margin-top: auto; height: calc(50px + 8px); /* height + borders */ visibility: hidden; } flex-container > flex-item:first-child { margin-top: auto; display: flex; } flex-container > flex-item:last-child { margin-top: auto; margin-bottom: auto; border: 4px solid chartreuse; height: 50px; width: 50px; } flex-container > flex-item:first-child > flex-item { border: 4px solid aqua; height: 50px; width: 50px; margin: 0 5px; } <flex-container> <flex-item><!-- flex container --> <flex-item></flex-item> <flex-item></flex-item> <flex-item></flex-item> </flex-item> <flex-item></flex-item> </flex-container> method #4: add flex: 1 top , bottom items
starting method #2 or #3 above, instead of worrying equal height top , bottom items maintain equal balance, give each 1 flex: 1. force them both consume available space, centering middle item.
you can add display: flex bottom item in order align content.
method #5: css grid layout
this may cleanest , efficient method. there no need absolute positioning, fake elements or other hackery.
simply create grid 3 rows. center-align items in second , third rows. first row can remain empty.
grid-container { display: grid; grid-template-rows: repeat(3, 1fr); align-items: center; justify-items: center; border: 4px solid blue; height: 300px; width: 300px; } grid-item:nth-child(2) { display: flex; } grid-item:nth-child(2)>flex-item { width: 50px; height: 50px; margin: 0 5px; border: 4px solid aqua; } grid-item:nth-child(3) { border: 4px solid chartreuse; height: 50px; width: 50px; } <grid-container> <grid-item></grid-item> <grid-item><!-- flex container --> <flex-item></flex-item> <flex-item></flex-item> <flex-item></flex-item> </grid-item> <grid-item></grid-item> </grid-container> 
Comments
Post a Comment