Flexbox
Flexbox is short for Flexible Box Layout, and can help you arrange elements in a row or column, vertically center items, and make elements equal height. Flexbox allows you to define 1-D layouts. It works from the content out. Use it for rows or columns of similar elements. You don’t need to set the size, because that is determined by the content.
When you set display: flex; on an element, it becomes a flex container:
- All direct child elements become flex items
- flex items align side by side, left to right, in a row. Use
flex-directionto change this. - size is determined by the contents.
- flex items align side by side, left to right, in a row. Use
- By default, flex items align side by side, left to right
- A flex container takes up 100% of its available width, while the height is determined natually by its contents. The
line-heightof the text inside each flex item is what determines the height of each item. - Margins between flex items do not collapse like in the regular document flow.
A flex container has two axises:
- Main axis, which goes the same direction as the flex-direction setting. Ex:
row(default), it goes left to right.column, top to bottom. - Cross axis runs perpendicular to main axis
In general, start a flexbox with the following methods:
- Apply
display: flexto the flex container. - Set a
gaporflex-direction, as needed. - Declare
flexvalues for the flex items to control their size, as needed.
Flex container
Apply display: flex to an element to turn it into a flex container, and all of its children become flex items. By default, flex items are the same height, and the height is determined by their content.
If you use
display: inline-flex, all elements become flex items, but they are inline elements instead of block.You will rarely use
inline-flex.
Flex items
When arranged in a row, flex items are placed horizontally along the main axis, and vertically along the cross-axis. Column layouts have a vertical main axis and horizontal cross axis.
Size
The flex property controls the size of the flex items along the main axis:
- Setting just one value sets the
flex-growproperty, and flex-shrink is set to 1, and flex-basis is set to 0. The flex-basis setting means there is no default width and the flex item grows according to available space. flex: 0;means that the flex item will not grow beyond its default sizeflex: auto;
By default, flex is set to flex: 0 1 auto (flex: <grow> <shrink> <basis>). It consists of three properties: flex-grow, flex-shrink, and flex-basis:
flex-basis: Defines a starting size of an element beforeflex-groworflex-shrinkare applied. Set this like you would set a width, with px, ems, percentages.- When you set
flex-basistoauto, then flexbox looks to see if there is a definedwidth. If so, it uses thewidth. Otherwise, it uses the contents to size the item. - By default, this is set to
auto. When set toauto, the browser checks if there is awidthdeclared on the element. If there is awidth, the browser uses thewidthsetting. If there is nowidth, the browser determines the size by the item’s contents. If you have awidthset, butflex-basisis set to anything other thanauto, then the browser ignores thewidthsetting.
- When you set
flex-grow: When the browser calculates theflex-basis, it does not necessarily fill the width of the flex container. Any remaining space is consumed according to theflex-growsetting on each flex item.- If
flex-growis set to 0, the item will not grow beyond itsflex-basisvalue. If it is set to any number other than 0, then the items grow until the space is used. - The
flex-growvalue acts as a weight. For example, if you set item A to1and item B to2, then item B will take up twice as much of the remaining space as item A.
- If
flex-shrink: Indicates whether it should shrink to prevent overflow in the event that the flex items’ initial size is larger than the flex container.flex-shrink: 0;means that the item does not shrink.- Items with a higher value shrink more than items with a lower value.
The shorthand flex property is usually all you need. For example, the following styles creates two flex items, one twice as gig as the other, with a gap:
.flex {
display: flex;
gap: var(--gap-size);
}
.column-main {
flex: 2;
}
.column-sidebar {
flex: 1;
}
When you need flex items to grow to fill their container, set flex to any value other than 0.
Another example sets flex-basis for each item to 33% of the flex container width. We also set flex-shrink to 1 so the items can shrink, as needed. This is helpful if you use a flex gap in your styles–the browser starts with the specified flex-basis, but then shrinks the flex items depending on other styles that use the same space, such as gap:
dl {
display: flex;
justify-content: center;
gap: 12px; /* gap that takes away from flex item size */
}
dl > div {
flex-basis: 33%; /* 1/3 of container */
flex-shrink: 1; /* browser adjusts for gap */
}
Flex direction
Add the flex-direction style to the flex container:
- When you change the flex direction to
column, that means thatflex-basis,flex-grow, andflex-shrinkapply to the element height, not width. The flex container’s height is still determined by the contents of its flex items when you useflex-direction: column;. - Swaps the direction of the main-axis and the cross-axis.
- For
flex-directionis a row, theflexproperty applies to the width of the container. Whenflex-directionis column, theflexproperty applies to the height of the container.
Flex basis and flex directions
If you set flex-basis to anything other than auto, flexbox ignores any height setting and only uses the contents. This is because flex-grow and flex-shrink begin calculating the sizing values at 0. If the flex item is empty, then it will not have any height.
This is tricky when you are using flex-direction: column;. When arranged in a row, flex items take up the width of their container because they are block elements. When arranged in a column, flex items default to the height of their container because they are block elements. If there is no content, that height is 0.
Depending on the flex-direction, flex-basis refers to the following:
- row: width
- column: height
Flex container properties
Apply the following properties to the flex container:
.flex-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
/* flex-flow is shorthand for flex-direction and flex-wrap */
flex-flow: column wrap;
/* justify-content uses the main axis. Think about setting text. */
justify-content: space-between;
/* align-* props use the cross-axis */
align-items: flex-start;
/* align-content works only when flex-wrap is enabled. It
controls the spacing of the flex rows along the cross axis. */
align-content: stretch;
gap: 1rem;
row-gap: 1rem;
column-gap: 1rem;
}
flex-wrap: column/column-reverseonly works when something constrains the container.
justify-content, align-items, and align-content all accept the following values:
flex-start,start,leftflex-end,end,rightcenterspace-betweenspace-aroundspace-evenly
Flex item properties
Apply the following properties to the flex container:
.flex-item {
order: 3;
flex-grow: 1;
flex-shrink: 2;
flex-basis: auto;
flex: 1;
/* uses cross-axis, overrides the container align-items
value. Ignored if item has margin: auto on cross-axis. */
align-self: flex-start;
}
align-self accepts the following properties:
autoflex-start,start,self-startflex-end,end,self-endcenterstretchbaseline
Use cases
Centered layout in viewport
To center an element with Flexbox, you can make the <body> element the flex container, and then center the flex items verticaly and horizontally:
body {
display: flex;
justify-content: center;
align-items: center;
}
Cards
You can use flexbox to make cards that are all the same size. For example, if you have a row of cards with a button at the bottom, you can push the button all the way to the bottom by setting flex-grow and flex-shrink to 1, and flex-basis to auto. You can also use the flex: 1; shorthand:
<div class="cards">
<div class="card">
<div class="content">
<p>This card doesn't have much content.</p>
</div>
<footer>Card footer</footer>
</div>
<!-- more cards... -->
</div>
.card {
display: flex;
flex-direction: column;
}
.card .content {
/* flex: 1 1 auto; */
flex: 1;
}
Because the div.content is the only item that can grow, it grows to fill up its container. When flex-direction is set to column, the items grow to fill the height of the container.
Forms and search bars
<form class="example">
<div class="wrapper">
<input type="text" id="text">
<input type="submit" value="Send">
</div>
</form>
.wrapper {
display: flex;
}
.wrapper input[type="text"] {
flex: 1 1 auto;
}