Guide: Sizing things
Sizing happens as a collaboration between a FlexItem and its parent FlexContainer.
- FlexItem: sets the initial size of a UI element
- (it's parent) FlexContainer: takes the sizes of all the child FlexItems, manipulates each one to make it fit with the others.
Configuring FlexItem settings
Flexbox layouts use two parts of CSS, giving us not one but two sets of size options for FlexItems, with the two interacting to produce the final size.
Options part 1: Flexbox/flex-basis
The first set of options is at the top of the Inspector, and is the settings "specific to FlexBox":
The main settings are:
- "flex-basis": this defines the FlexItem's 'main' length inside its parent FlexContainer
- "flex-grow": when the parent has spare space, defines how much this FlexItem should 'expand to fill'
- "flex-shrink": when the parent has too little space to hold all the children, defines how much this FlexItem should 'shrink to fit'
Additionally, this screen calculates some values and displays them for you as a reminder. In the example above, the first row is telling us that:
- This item is in a horizontal row (defined by its parent FlexContainer)
- The final width, after performing all calculations, is "0 pixels"
...this is especially useful when you're trying to understand the net effect of both the main setttings and the secondary settings (which we'll get onto next).
Options part 2: CSS/width/height
The second set of options is at the bottom, and comes with a live Preview of how they impact the item and its own children and siblings. These are the traditional CSS setttings.
The secondary settings are:
- "margin": how much this item "pushes away" its siblings, the space OUTSIDE it
- "padding": (ONLY for FlexItems that are themselves FlexContainers): puts space around its child FlexItems
- "width": overrides and defaults for width
- "height": overrides and defaults for height
Two stages of sizing
Sizing happens in two stages: first the FlexItems have their sizes calculated, then the FlexContainer tries to fit them in to the available space, using their "grow" and "shrink" settings, resizing them as necessary.
This means that the actual 'size' of a FlexItem is rarely the same as the size set on the FlexItem itself (unless you set both 'grow' and 'shrink' to 0, which prevents the FlexContainer from altering the sizing).
Auto Sizing: CONTENT
The most common FlexBasis is the default value (AUTO), which is treated as "CONTENT". CONTENT means "auto-calculate my correct size by looking at the content of this UI element".
e.g. for a FlexItem that has a Label/Text component attached (or as its only child), if FlexBasis is set to CONTENT then it will size itself to be "the width of that text" when its parent is using a Direction of Row or ReversedRow, and will size itself to be "the height of that text" when its parent is using Column or ReversedColumn.
e.g. for a FlexItem with an Image component, if its set to CONTENT, it will make itself the size of the Image in pixels.
Explicit Sizing: FlexBasis, Width, and Height
Using FlexBasis
Flexbox only allows FlexItems to control their size in a single axis - specifically "whichever axis the parent FlexContainer is currently set to use as its Direction". The FlexBasis property on each FlexItem provides this control.
There are many cases where you want an explicit size - eg you want to make a side-navbar be "250 pixels wide", or "10%". In those cases you change the FlexBasis to PIXELS or PERCENT.
Warning
⚠ Note: FlexBasis only sets the FlexItem's initial size (hence "basis"); as we'll see below, that size is usually altered by the parent FlexContainer afterwards.
Overriding width and height
However, if you leave the FlexBasis to its default value you can also override both the width and the height, again either in pixels or percent. Its important to be aware that these 'explicit' width and/or height values are only used if the FlexBasis has been disabled by setting it to its default value (AUTO).
Note
💡 This is technically a legacy feature of CSS3, but its very convenient so its used often.
Why have two ways of setting the size? Well, this is mainly so that Flexbox can change direction (from horizontal layout to vertical, or vice versa) and some/all of the layout will automatically adapt to the new direction. It's recommended that you try to use explicit FlexBasis values and avoid the explicit width/height where possible.
There are always edge-cases where you need to set the width AND height (where FlexBasis only allows you to control one), so this is usually where you see both beind used.
Warning
⚠ As with FlexBasis, setting the width/height only sets the FlexItem's desired/initial size -- the FlexContainer will usually alter it afterwards.
Constraints: min-width and max-width
Irrespective of whether you use FlexBasis or Width/Height, you can set minimum and maximum values for either direction.
These are generally applied after all other calculations, which means they are applied AFTER the FlexContainer's changes.
FlexContainer: post-sizing of FlexItems
After the child FlexItems have all been sized, the FlexContainer tries to fit them in to itself, and whatever size/space its been given by its own parent.
Each FlexItem can refuse to be made smaller than its initial size (set its 'shrink' to 0), or refuse to be expanded to fill available space (set its 'grow' to 0). Otherwise the grow/shrink values are used to tell the FlexContainer how much each item is willing to be changed relative to its siblings.
Note
💡 The interaction betwen "min" and "max" values and the growing, shrinking, etc is non-trivial - if you are not experienced with CSS3 already you may sometimes be surprised by the results. To try and support all possible designs/layouts, there is a lot of expressive power here, and you may need to experiment and tweak your settings to get the exact behaviour you intended.
Margins and Box-Modes
If you set a FlexItem to use "ContentBox" mode then the sizes (FlexBasis, Width, Min-Width, etc) are applied before adding the Margins on. If you set it to "BorderBox" mode (the default recommended by CSS, but for legacy reasons not turned on by default) then the Margins are included in those calculations.
Margins are applied to a FlexItem itself (they force siblings to be pushed away from it by that amount).