coryhouse/reactjsconsulting

Flexbox

Opened this issue · 0 comments

Flexbox

Josh's wonderful interactive Flexbox guide

image

Old school: Split up page into 12 columns.

.col-1 {width: 8.33%;}
.col-2 {width: 16.66%;}
.col-3 {width: 25%;}
.col-4 {width: 33.33%;}
.col-5 {width: 41.66%;}
.col-6 {width: 50%;}
.col-7 {width: 58.33%;}
.col-8 {width: 66.66%;}
.col-9 {width: 75%;}
.col-10 {width: 83.33%;}
.col-11 {width: 91.66%;}
.col-12 {width: 100%;}
  • Efficiently layout items in a container (use Grid for large scale layout), even when their size isn't known (hence, flex box).
  • Big idea: Flex width/height to best fit the space. Expands to fill space or shrinks to prevent overflow.
  • Benefits: Simpler markup (no more wrappers, floats, etc), and reduced JS needs
  • Direction agnostic (unlike block which is vertical, and inline which is horizontal)
  • Browser support
  • Bootstrap uses Flexbox behind the scenes
  • container with items - img
  • Items are laid out following either the main axis from main-start to main-end or via the cross axis from cross-start to cross end. Main is not necessarily horizontal. The direction of each is impacted by flex-direction.

Key Terms

  • main size - A flex item's width/height (whichever is the main dimension).
  • cross axis - Perpendicular to main axis
  • cross-start | cross-end - Flex lines start at cross-start
  • cross-size - Width or height of flex item (whichever is in the cross dimension)

Properties

display

.container {
  display: flex; /* or inline-flex */
}

flex-direction
row is ltr, column is top to bottom.

.container {
  flex-direction: row | row-reverse | column | column-reverse;
}

flex-wrap
By default, all items will try to fit on one line. So the default is nowrap. wrap will wrap top to bottom/left. wrap-reverse will reverse the align-items setting and the direction new lines are created. So it will wrap items to the top/right instead of the bottom/left (depending on the flex-direction). And note order: Flex wraps first, then shrinks/grows. if enabled. Regarding grow/shrink/ the item's current line is the only space that matters.

.container {
  flex-wrap: nowrap | wrap | wrap-reverse;
}

flex-wrap demo

flex-flow (applies to parent flex container)
Shorthand for flex-direction and flex-wrap which together define the container's main and cross axes. Again, default is row nowrap

flex-flow: row wrap;

Above is same as:

flex-direction: row; flex-wrap: wrap;

justify-content
Defines alignment along the main axis. Distributes extra free space. Image

.container {
  justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
}

align-items
Same as justify-content, but defines alignment on the cross axis. Image. Default: stretch.

.container {
  align-items: stretch | flex-start | flex-end | center | baseline;
}

align-content
This aligns the lines, so only applies when wrapping. Like justify-content, but for the cross-axis. Image

.container {
  align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}

Properties for flex items

gap
gap allows us to create space in-between each Flex child, along the primary axis.

margin-left and margin-right
Set this to auto to add space around a specific element. It will gobble up the extra space, and apply it to the element's margin. It gives us precise control over where to distribute the extra space.

Screenshot 2022-12-03 at 7 58 08 AM

order
By default, flex items are laid out in source order. Can change using order:

.item {
  order: <integer>; /* default is 0 */
}

Any item with an order of 1 or higher gets sent to the back of the line. A negative order moves the item to the front of the line. Items with the same order setting will honor their source order.

flex-grow
Let item grow if necessary. Dictactes the amount of the available space in the container the item should take up. If all items have flex-grow set to the same value, the remaining space will be distributed equally. If one is set to 2, and others are set to one, it will take up twice as much space.

.item {
  flex-grow: <number>; /* default 0 */
}

flex-shrink
Opposite of flex-grow. Describes how the content should react when there's not enough space. Relative like flex-grow. Set to 0 to not allow an item to shrink.

.item {
  flex-shrink: <number>; /* default 1 */
}

flex-basis
The new and improved version of width and height, for flex, but only applies to the primary axis. Defines the element's default size before the remaining space is distributed. It's not a guarantee. It merely specifies an an "ideal" when there's enough space. So it's merely a starting point. This setting overrides width if set. min-width sets a lower limit. max-width sets an upper limit. Like width, can use % or px. This effects height instead when in column mode.

Also, when the total space available falls below the total of flex-basis for all elements, shrinking occurs. So flex-shrink effects the behavior at that point. And when extra space is available, their flex-grow setting effects if and how they grow.

Finally, if you set flex-basis lower than min-width, it becomes the min value. Same story with max-width.

  • auto: use items width or height property. The default.
  • content: size it based on item's content
.item {
  flex-basis: <length> | auto; /* default auto */
}

In general, we can use width and flex-basis interchangeably in a Flex row, but there are some exceptions. For example, the width property affects replaced elements like images differently than flex-basis. Also, width can reduce an item below its minimum size, while flex-basis can't.

flex
Shorthand for flex-grow, flex-shrink, and flex-basis combined, in that order. Only first param is required. Default is 0 1 0px. You can leave off the 2nd param too (since the last one is px or auto, it's not ambiguous. For example, this sets only grow and basis: flex: 0 300px;

.item {
  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

Also, handy auto shortcut (grow, shrink, and use size as basis):

.item {
  flex: auto; /* sets flex-grow: 1; flex-shrink: 1; flex-basis: auto; */
}

And handy none shortcut (don't grow, don't shrink, and use your size as a basis):

.item {
  flex: none; /* flex-grow: 0; flex-shrink: 0; flex-basis: auto */
}

align-self
Override alignment for a single item. Works like align-items.

.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

It's recommended to use this shorthand property. It sets the other values intelligently.

Cross-browser support

  • There are older versions of Flexbox (used by IE10/11.
  • Use autoprefixer

Useful tools / Resources

flexplorer
Box alignment cheatsheet - Compares Flexbox and Grid alignment
Solved by Flexbox - Examples of problems solved by Flexbox
Guide to Flexbox on CSS Tricks
List of bugs with current status

Examples

2 column responsive layout
Responsive table on Stackblitz (also in this repo)
Calendar Codepen
Full site layout - Compare to Grid version