When I started to learn flexbox, I experimented with division elements. Division elements are block elements by default, which means they display one beneath the other as shown in the screenshot below (fig 1).
To make division elements flex side by side, we just need to set the container division's "display" property to "flex" like so: "display: flex" as shown in the HTML code below (fig 2). The rest of the CSS properties are optional, which I've added just to make everything look better spaced out.
Within the above HTML code, you'll see that we have a parent division which has been assigned the class name "flex-container", and four inner divisions. Notice that the display property value for the four inner divisions is unchanged, and so it's the container itself that kind of owns the flexbox functionality...
The screenshot below (fig 3) shows the result of the above code.
To elaborate on what I mean by "owns" – CSS flexbox has what we call: "Flex Container Properties" and "Flex Item Properties", but if the container's display property isn't set to flex as discussed above, then those container and item properties won't do anything.
Before we continue to discuss and understand more about CSS flexbox, you might want to watch the following video tutorial. I demonstrate all of the most important flexbox features, and analyse what is happening in considerable detail.
The most important flexbox container properties are:
The most important flexbox item properties are:
CSS Flexbox refers to the horizontal and vertical axes as the "Main Axis" and the "Cross Axis". By default, the flex-direction property is set to "row", which I initially thought meant horizontal, until I read about the CSS "writing-mode" property – MDN Web Docs "The writing-mode CSS property sets whether lines of text are laid out horizontally or vertically, as well as the direction in which blocks progress."
So the default writing mode value "horizontal-tb" does indeed result in the flex direction being horizontal when "flex-direction" is set to its default value row, and vertical when flex-direction is set to "column". Flexing occurs along the main axis, and so when the flex direction is set to column, the main axis runs vertical as shown below in screenshot (fig 4).
When you set the "flex-wrap" property to "wrap", it causes the items that cannot fit on the current row, to wrap onto the next row.
Flex wrapping occurs either horizontally or vertically depending on the flex direction as discussed above. For example when "flex-direction" is set to "column" as shown above in (fig 4), wrapping occurs horizontally, i.e. division 1 has wrapped onto a new column. When flex-direction is set to "row" as shown in screenshot (fig 5), wrapping occurs vertically onto a new row.
The "justify-content" property is used to control how items are spaced out in the given row. There are quite a few values to choose from, and so I've only shown five, commonly used values as shown below in screenshot (fig 6).
The difference between these two properties can be confusing, so it's worth watching how I demonstrate the difference in the video... further up the page.
These two properties are both vertical alignment properties as show below in (fig 7 and fig 8), in contrast to "justify-content" controlling horizontal alignment as shown above in (fig 6), but there is a fundamental difference in how both vertical alignment properties work, and so they both play an important roll in CSS flexbox.
The "align-items" property aligns all the items in a given row, relative to the row's available height. For example if you look at (fig 7), you can see that align-items is set to "center", which results in the items being vertically central (concentric) to one another along any given row.
The "align-content" property aligns all the rows relative to one another. For example if you look below at (fig 8) in contrast to (fig 7), you can see that align-content is now set to "flex-start", which pushes both rows upwards against each another.
Screenshot (fig 10) below, demonstrates how the "flex-grow" property is being used to stretch (i.e. expand) the division elements via inline styling (fig 9). The default value is 0 which means no growing occurs. How much an individual element grows, is its grow value as a percentage (i.e. proportion) of all the grow values added together.
The width of each division element as determined by the text it contains + padding + borders + margins, when subtracted from the container's total width = available space. That available space is then divided up in accordance with the grow value proportions as mentioned above. Each grow amount is then added to the corresponding division.
If the sum of all the grow values >= 1, then all the available space will be used up to fill the container. However, it's perfectly valid to use fractional values, and so for example if flex-grow is set to 0.125 for each of the four divisions, then only 50% of the available space will be used up.
The default value for the "flex-shrink" property is 1, which causes the container items to shrink if necessary to fit inside the container. This default behaviour could easily result in the programmer being unaware that flex-shrink is shrinking the items.
So I've revealed the amount that flex-shrink would be reducing the width of the items, shown below in (fig 12), by setting its value to 0 as shown in (fig 11), thereby disabling flex-shrink. The amount that each individual item shrinks is proportional to its shrink value, exactly like it works for "flex-grow", which essentially makes flex-shrink the exact opposite of flex-grow.
The "flex-basis" property tells the browser to treat items as having specific widths, which are then used to calculate the flex spacing between or around the items. Flex basis is best understood in conjunction with "flex-grow", because the final size of any item is directly dependent its own initial size and the container's available space.
For example if flex-basis is set to some value – let's say for all items it's set to 0... then the available space available becomes the full width of the container (minus borders etc), resulting in all items expanding from 0 to an equal width (based on each having the same grow value), regardless of the item's true initial width.
In the flexbox video tutorial further up the page, I've included a nice calculation, demonstrated with the assistance of VS Code's development tools.