{"id":8929,"date":"2026-03-17T06:40:39","date_gmt":"2026-03-17T11:40:39","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=8929"},"modified":"2026-03-17T06:40:40","modified_gmt":"2026-03-17T11:40:40","slug":"flexbox-masonry-layout-explained-with-math","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/flexbox-masonry-layout-explained-with-math\/","title":{"rendered":"Flexbox Masonry Layout (Explained with Math)"},"content":{"rendered":"\n<p>We&#8217;re going to get into building a somewhat unusual layout. It&#8217;s going to be multiple rows of differently sized elements, each with a <em>known<\/em> aspect ratio (like images), which span the full and exact width of the container. <\/p>\n\n\n\n<p>We&#8217;re going to do this with flexbox in CSS and have a deep and very mathematical look at how it works.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Does Flexbox Distribute Space?<\/h2>\n\n\n\n<p>It will be first useful to understand flexbox itself and how the different properties affect how the space is used.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.container<\/span> {\n  <span class=\"hljs-attribute\">display<\/span>: flex;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Flex Properties<\/h3>\n\n\n\n<p>Certain things go on the flex container itself.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.container<\/span> {\n  <span class=\"hljs-attribute\">display<\/span>: flex;\n  <span class=\"hljs-attribute\">flex-direction<\/span>: row; <span class=\"hljs-comment\">\/* Default. Could be \"column\" *\/<\/span>\n  <span class=\"hljs-attribute\">gap<\/span>: <span class=\"hljs-number\">1rem<\/span>; <span class=\"hljs-comment\">\/* size of the space between items *\/<\/span>\n  <span class=\"hljs-attribute\">flex-wrap<\/span>: wrap; <span class=\"hljs-comment\">\/* Allows items to wrap. Default is \"nowrap\" *\/<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Some important properties get applied to the items inside the container. These are a bit trickier to understand and use.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.container<\/span> {\n  ...\n\n  &gt; .item {\n     <span class=\"hljs-attribute\">flex-basis<\/span>: <span class=\"hljs-number\">100px<\/span>; <span class=\"hljs-comment\">\/* The size of the item before growing or shrinking happens. *\/<\/span>\n     <span class=\"hljs-attribute\">flex-grow<\/span>: <span class=\"hljs-number\">1<\/span>; <span class=\"hljs-comment\">\/* Factor that decides how much of the remaining space the item receives. *\/<\/span>\n     <span class=\"hljs-attribute\">flex-shrink<\/span>: <span class=\"hljs-number\">1<\/span>; <span class=\"hljs-comment\">\/* Factor that decides how much of the exceeding space the item loses. *\/<\/span>\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">Assumptions and Simplifications<\/h3>\n\n\n\n<p>The full flexbox algorithm defined in <a href=\"https:\/\/www.w3.org\/TR\/css-flexbox-1\/#resolve-flexible-lengths\">the specification<\/a> is more complex than the model we&#8217;re about to get into. Layout is complicated! I want to focus specifically on <em>space distribution<\/em> here, so to keep things focused, were going to ignore a few aspects of flexbox layout for now.<\/p>\n\n\n\n<p>The things we&#8217;re ignoring are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The <code>min-width<\/code> and <code>max-width<\/code> (or height, or the logical property equivalents) on items.<\/li>\n\n\n\n<li>The algorithm is described as a single distribution step, while the specification says it may redistribute when items reach size limits.<\/li>\n\n\n\n<li>We&#8217;re only considering a flex container with <code>flex-direction: row<\/code> and where the main axis is horizontal.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Conceptual Model<\/h2>\n\n\n\n<p>The process for distributing space in the row works as follows.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Initial Free Space<\/h3>\n\n\n\n<p>The first step is to determine how much space is available or unavailable in the row. The initial <em>free<\/em> space is the flex container width minus the sum of the <code>flex-basis<\/code> of all items in the row and minus the gaps between them.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Positive Initial Free Space (Growing)<\/h3>\n\n\n\n<p>If the initial free space is <em>positive<\/em>, items <em>grow<\/em> to fill the container:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If the sum of the <code>flex-grow<\/code> of all items in the row is less than 1, the free space is scaled by this sum. This means less of the total free space will be distributed, and items will not fill the container.<\/li>\n\n\n\n<li>The free space is distributed among items, proportional to their <code>flex-grow<\/code> values.<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_019cd91c-d135-791e-adb4-12d6db9320ed\" src=\"\/\/codepen.io\/editor\/anon\/embed\/019cd91c-d135-791e-adb4-12d6db9320ed?height=250&amp;theme-id=1&amp;slug-hash=019cd91c-d135-791e-adb4-12d6db9320ed&amp;default-tab=result\" height=\"250\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed 019cd91c-d135-791e-adb4-12d6db9320ed\" title=\"CodePen Embed 019cd91c-d135-791e-adb4-12d6db9320ed\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Negative Free Space (Shrinking)<\/h3>\n\n\n\n<p>If the initial free space is <em>negative<\/em>, items shrink to fit the container:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If the sum of the <code>flex-shrink<\/code> of all items in the row is less than 1, the free space is scaled by this sum. This means less of the total free space will be distributed, and items will overflow the container.<\/li>\n\n\n\n<li>Each item has a scaled-flex-shrink, calculated as flex-shrink multiplied by flex-basis. This ensures smaller items aren\u2019t reduced to zero before larger ones shrink noticeably.<\/li>\n\n\n\n<li>The negative free space is distributed among items, proportional to their&nbsp;<strong>scaled <code>flex-shrink<\/code><\/strong>&nbsp;values. Items with larger scaled-flex-shrink receive more of the negative space and therefore shrink more.<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_019cf1d3-0d44-7149-9dc1-441b88132efd\" src=\"\/\/codepen.io\/editor\/anon\/embed\/019cf1d3-0d44-7149-9dc1-441b88132efd?height=250&amp;theme-id=1&amp;slug-hash=019cf1d3-0d44-7149-9dc1-441b88132efd&amp;default-tab=result\" height=\"250\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed 019cf1d3-0d44-7149-9dc1-441b88132efd\" title=\"CodePen Embed 019cf1d3-0d44-7149-9dc1-441b88132efd\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">What About Wrapping?<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Without wrapping, all items remain in a single row.<\/li>\n\n\n\n<li>With wrapping enabled, each row contains as many items as fit, including gaps. Items that don\u2019t fit move to the next row. The grow or shrink distribution described above is <strong>applied independently to each row.<\/strong><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Mathematical Model<\/h2>\n\n\n\n<p>Now let&#8217;s formalize what we described conceptually, in mathematical terms. We first define the variables:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msub><mi>w<\/mi><mi>i<\/mi><\/msub><mspace width=\"1em\"><\/mspace><mtext>final&nbsp;width&nbsp;of&nbsp;item&nbsp;<\/mtext><mi>i<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">w_i \\quad \\text{final width of item } i<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>F<\/mi><msub><mi>B<\/mi><mi>i<\/mi><\/msub><mspace width=\"1em\"><\/mspace><mtext>flex-basis&nbsp;of&nbsp;item&nbsp;<\/mtext><mi>i<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">FB_i \\quad \\text{flex-basis of item } i<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>F<\/mi><msub><mi>G<\/mi><mi>i<\/mi><\/msub><mspace width=\"1em\"><\/mspace><mtext>flex-grow&nbsp;of&nbsp;item&nbsp;<\/mtext><mi>i<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">FG_i \\quad \\text{flex-grow of item } i<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>F<\/mi><mi>S<\/mi><msub><mi>H<\/mi><mi>i<\/mi><\/msub><mspace width=\"1em\"><\/mspace><mtext>flex-shrink&nbsp;of&nbsp;item&nbsp;<\/mtext><mi>i<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">FSH_i \\quad \\text{flex-shrink of item } i<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>I<\/mi><mi>F<\/mi><mi>S<\/mi><mspace width=\"1em\"><\/mspace><mtext>initial&nbsp;free&nbsp;space<\/mtext><\/mrow><annotation encoding=\"application\/x-tex\">IFS \\quad \\text{initial free space}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>n<\/mi><mspace width=\"1em\"><\/mspace><mtext>number&nbsp;of&nbsp;items&nbsp;in&nbsp;a&nbsp;row<\/mtext><\/mrow><annotation encoding=\"application\/x-tex\">n \\quad \\text{number of items in a row}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>Initial free space is:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>I<\/mi><mi>F<\/mi><mi>S<\/mi><mo>=<\/mo><mi>C<\/mi><mi>o<\/mi><mi>n<\/mi><mi>t<\/mi><mi>a<\/mi><mi>i<\/mi><mi>n<\/mi><mi>e<\/mi><mi>r<\/mi><mi>W<\/mi><mi>i<\/mi><mi>d<\/mi><mi>t<\/mi><mi>h<\/mi><mo>\u2212<\/mo><mrow><munderover><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>i<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/munderover><\/mrow><mi>F<\/mi><msub><mi>B<\/mi><mi>i<\/mi><\/msub><mo>\u2212<\/mo><mi>G<\/mi><mi>a<\/mi><mi>p<\/mi><mi>W<\/mi><mi>i<\/mi><mi>d<\/mi><mi>t<\/mi><mi>h<\/mi><mo>\u22c5<\/mo><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>n<\/mi><mo>\u2212<\/mo><mn>1<\/mn><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">IFS = ContainerWidth &#8211; \\sum_{i=1}^{n} FB_i &#8211; GapWidth \\cdot (n &#8211; 1)<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>If initial free space is positive, the item width is:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msub><mi>w<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mi>F<\/mi><msub><mi>B<\/mi><mi>i<\/mi><\/msub><mo>+<\/mo><mi>I<\/mi><mi>F<\/mi><mi>S<\/mi><mo>\u22c5<\/mo><mfrac><mrow><mi>F<\/mi><msub><mi>G<\/mi><mi>i<\/mi><\/msub><\/mrow><mrow><msubsup><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>k<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/msubsup><mi>F<\/mi><msub><mi>G<\/mi><mi>k<\/mi><\/msub><\/mrow><\/mfrac><mo>\u22c5<\/mo><mrow><mi>min<\/mi><mo>\u2061<\/mo><\/mrow><mrow><mo fence=\"true\" form=\"prefix\">(<\/mo><mn>1<\/mn><mo separator=\"true\">,<\/mo><mrow><munderover><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>k<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/munderover><\/mrow><mi>F<\/mi><msub><mi>G<\/mi><mi>k<\/mi><\/msub><mo fence=\"true\" form=\"postfix\">)<\/mo><\/mrow><\/mrow><annotation encoding=\"application\/x-tex\">w_i = FB_i + IFS \\cdot \\frac{FG_i}{\\sum_{k=1}^{n} FG_k} \\cdot \\min\\left(1, \\sum_{k=1}^{n} FG_k\\right)<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>If initial free space is negative, the item width is:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msub><mi>w<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mi>F<\/mi><msub><mi>B<\/mi><mi>i<\/mi><\/msub><mo>+<\/mo><mi>I<\/mi><mi>F<\/mi><mi>S<\/mi><mo>\u22c5<\/mo><mfrac><mrow><mi>F<\/mi><mi>S<\/mi><msub><mi>H<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><mi>F<\/mi><msub><mi>B<\/mi><mi>i<\/mi><\/msub><\/mrow><mrow><msubsup><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>k<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/msubsup><mi>F<\/mi><mi>S<\/mi><msub><mi>H<\/mi><mi>k<\/mi><\/msub><mo>\u22c5<\/mo><mi>F<\/mi><msub><mi>B<\/mi><mi>k<\/mi><\/msub><\/mrow><\/mfrac><mo>\u22c5<\/mo><mrow><mi>min<\/mi><mo>\u2061<\/mo><\/mrow><mrow><mo fence=\"true\" form=\"prefix\">(<\/mo><mn>1<\/mn><mo separator=\"true\">,<\/mo><mrow><munderover><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>k<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/munderover><\/mrow><mi>F<\/mi><mi>S<\/mi><msub><mi>H<\/mi><mi>k<\/mi><\/msub><mo fence=\"true\" form=\"postfix\">)<\/mo><\/mrow><\/mrow><annotation encoding=\"application\/x-tex\">w_i = FB_i + IFS \\cdot \\frac{FSH_i \\cdot FB_i}{\\sum_{k=1}^{n} FSH_k \\cdot FB_k} \\cdot \\min\\left(1, \\sum_{k=1}^{n} FSH_k\\right)<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Again, what about Wrapping?<\/h3>\n\n\n\n<p>Without wrapping, <em>n<\/em> is just the number of items. With wrapping enabled, the number of items in a row is the maximum <em>n<\/em> such that:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mrow><munderover><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>i<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/munderover><\/mrow><mi>F<\/mi><msub><mi>B<\/mi><mi>i<\/mi><\/msub><mo>+<\/mo><mi>G<\/mi><mi>a<\/mi><mi>p<\/mi><mi>W<\/mi><mi>i<\/mi><mi>d<\/mi><mi>t<\/mi><mi>h<\/mi><mo>\u22c5<\/mo><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mi>n<\/mi><mo>\u2212<\/mo><mn>1<\/mn><mo form=\"postfix\" stretchy=\"false\">)<\/mo><mo>\u2264<\/mo><mi>C<\/mi><mi>o<\/mi><mi>n<\/mi><mi>t<\/mi><mi>a<\/mi><mi>i<\/mi><mi>n<\/mi><mi>e<\/mi><mi>r<\/mi><mi>W<\/mi><mi>i<\/mi><mi>d<\/mi><mi>t<\/mi><mi>h<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">\\sum_{i=1}^{n} FB_i + GapWidth \\cdot (n &#8211; 1) \\leq ContainerWidth<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>And that\u2019s a wrap! Now we can more or less grasp how flexbox actually works.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Masonry Layout<\/h2>\n\n\n\n<p>Now that we know how flexbox works, we can come back to our objective: a layout consisting of items, each with a known aspect ratio, disposed in rows, with items in the same row sharing the same height, and each row spanning the full width of the container.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Layout Constraints<\/h3>\n\n\n\n<p>A. Each item having an aspect ratio:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mfrac><msub><mi>w<\/mi><mi>i<\/mi><\/msub><msub><mi>h<\/mi><mi>i<\/mi><\/msub><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">AR_i = \\frac{w_i}{h_i}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>Which can be rewritten as:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msub><mi>w<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><msub><mi>h<\/mi><mi>i<\/mi><\/msub><mspace width=\"2em\"><\/mspace><mtext>or<\/mtext><mspace width=\"2em\"><\/mspace><msub><mi>h<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mfrac><msub><mi>w<\/mi><mi>i<\/mi><\/msub><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><\/mrow><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">w_i = AR_i \\cdot h_i \\qquad \\text{or} \\qquad h_i = \\frac{w_i}{AR_i}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>B. Each row spanning the full width of the container:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mrow><munderover><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>i<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/munderover><\/mrow><msub><mi>w<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mi>C<\/mi><mi>o<\/mi><mi>n<\/mi><mi>t<\/mi><mi>a<\/mi><mi>i<\/mi><mi>n<\/mi><mi>e<\/mi><mi>r<\/mi><mi>W<\/mi><mi>i<\/mi><mi>d<\/mi><mi>t<\/mi><mi>h<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">\\sum_{i=1}^{n} w_i = ContainerWidth<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>C. Each item in the same row sharing the same height:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msub><mi>h<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mi>H<\/mi><mspace width=\"1em\"><\/mspace><mtext>for&nbsp;every&nbsp;<\/mtext><mi>i<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">h_i = H \\quad \\text{for every } i<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>Combining the constraints \u2014 plug C into A:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msub><mi>w<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><mi>H<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">w_i = AR_i \\cdot H<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>Plug the above into B:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mrow><munderover><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>i<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/munderover><\/mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><mi>H<\/mi><mo>=<\/mo><mi>C<\/mi><mi>o<\/mi><mi>n<\/mi><mi>t<\/mi><mi>a<\/mi><mi>i<\/mi><mi>n<\/mi><mi>e<\/mi><mi>r<\/mi><mi>W<\/mi><mi>i<\/mi><mi>d<\/mi><mi>t<\/mi><mi>h<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">\\sum_{i=1}^{n} AR_i \\cdot H = ContainerWidth<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p><em>H<\/em> can be taken outside the summation:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>H<\/mi><mo>\u22c5<\/mo><mrow><munderover><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>i<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/munderover><\/mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mi>C<\/mi><mi>o<\/mi><mi>n<\/mi><mi>t<\/mi><mi>a<\/mi><mi>i<\/mi><mi>n<\/mi><mi>e<\/mi><mi>r<\/mi><mi>W<\/mi><mi>i<\/mi><mi>d<\/mi><mi>t<\/mi><mi>h<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">H \\cdot \\sum_{i=1}^{n} AR_i = ContainerWidth<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>Divide by:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mrow><munderover><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>i<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/munderover><\/mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><\/mrow><annotation encoding=\"application\/x-tex\">\\sum_{i=1}^{n} AR_i<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>H<\/mi><mo>=<\/mo><mfrac><mrow><mi>C<\/mi><mi>o<\/mi><mi>n<\/mi><mi>t<\/mi><mi>a<\/mi><mi>i<\/mi><mi>n<\/mi><mi>e<\/mi><mi>r<\/mi><mi>W<\/mi><mi>i<\/mi><mi>d<\/mi><mi>t<\/mi><mi>h<\/mi><\/mrow><mrow><msubsup><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>i<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/msubsup><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><\/mrow><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">H = \\frac{ContainerWidth}{\\sum_{i=1}^{n} AR_i}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>Voil\u00e0, this last expression tells us that an <em>H<\/em> always exists such that it respects the layout constraints.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Plugging the Constraints into the Flexbox Model<\/h3>\n\n\n\n<p>A. Because each item has an aspect ratio:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msub><mi>h<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mfrac><msub><mi>w<\/mi><mi>i<\/mi><\/msub><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><\/mrow><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">h_i = \\frac{w_i}{AR_i}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>B. For each row to span the full width of the container we need:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mrow><mi>min<\/mi><mo>\u2061<\/mo><\/mrow><mrow><mo fence=\"true\" form=\"prefix\">(<\/mo><mn>1<\/mn><mo separator=\"true\">,<\/mo><mrow><munderover><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>j<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/munderover><\/mrow><mi>F<\/mi><msub><mi>G<\/mi><mi>j<\/mi><\/msub><mo fence=\"true\" form=\"postfix\">)<\/mo><\/mrow><mo>=<\/mo><mn>1<\/mn><mspace width=\"2em\"><\/mspace><mtext>and<\/mtext><mspace width=\"2em\"><\/mspace><mrow><mi>min<\/mi><mo>\u2061<\/mo><\/mrow><mrow><mo fence=\"true\" form=\"prefix\">(<\/mo><mn>1<\/mn><mo separator=\"true\">,<\/mo><mrow><munderover><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>j<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/munderover><\/mrow><mi>F<\/mi><mi>S<\/mi><msub><mi>H<\/mi><mi>j<\/mi><\/msub><mo fence=\"true\" form=\"postfix\">)<\/mo><\/mrow><mo>=<\/mo><mn>1<\/mn><\/mrow><annotation encoding=\"application\/x-tex\">\\min\\left(1, \\sum_{j=1}^{n} FG_j\\right) = 1 \\qquad \\text{and} \\qquad \\min\\left(1, \\sum_{j=1}^{n} FSH_j\\right) = 1<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>We can guarantee that by putting:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>F<\/mi><msub><mi>G<\/mi><mi>i<\/mi><\/msub><mo>\u2265<\/mo><mn>1<\/mn><mspace width=\"2em\"><\/mspace><mtext>and<\/mtext><mspace width=\"2em\"><\/mspace><mi>F<\/mi><mi>S<\/mi><msub><mi>H<\/mi><mi>i<\/mi><\/msub><mo>\u2265<\/mo><mn>1<\/mn><mspace width=\"1em\"><\/mspace><mtext>for&nbsp;every&nbsp;<\/mtext><mi>i<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">FG_i \\geq 1 \\qquad \\text{and} \\qquad FSH_i \\geq 1 \\quad \\text{for every } i<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>We use the first two constraints: apply B to the flexbox item final widths and plug that into A.<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msub><mi>h<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mfrac><mrow><mi>F<\/mi><msub><mi>B<\/mi><mi>i<\/mi><\/msub><\/mrow><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><\/mrow><\/mfrac><mo>+<\/mo><mi>I<\/mi><mi>F<\/mi><mi>S<\/mi><mo>\u22c5<\/mo><mfrac><mrow><mi>F<\/mi><msub><mi>G<\/mi><mi>i<\/mi><\/msub><\/mrow><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><msubsup><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>k<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/msubsup><mi>F<\/mi><msub><mi>G<\/mi><mi>k<\/mi><\/msub><\/mrow><\/mfrac><mspace width=\"2em\"><\/mspace><mtext>and<\/mtext><mspace width=\"2em\"><\/mspace><msub><mi>h<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mfrac><mrow><mi>F<\/mi><msub><mi>B<\/mi><mi>i<\/mi><\/msub><\/mrow><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><\/mrow><\/mfrac><mo>+<\/mo><mi>I<\/mi><mi>F<\/mi><mi>S<\/mi><mo>\u22c5<\/mo><mfrac><mrow><mi>F<\/mi><mi>S<\/mi><msub><mi>H<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><mi>F<\/mi><msub><mi>B<\/mi><mi>i<\/mi><\/msub><\/mrow><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><msubsup><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>k<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/msubsup><mi>F<\/mi><mi>S<\/mi><msub><mi>H<\/mi><mi>k<\/mi><\/msub><mo>\u22c5<\/mo><mi>F<\/mi><msub><mi>B<\/mi><mi>k<\/mi><\/msub><\/mrow><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">h_i = \\frac{FB_i}{AR_i} + IFS \\cdot \\frac{FG_i}{AR_i \\cdot \\sum_{k=1}^{n} FG_k} \\qquad \\text{and} \\qquad h_i = \\frac{FB_i}{AR_i} + IFS \\cdot \\frac{FSH_i \\cdot FB_i}{AR_i \\cdot \\sum_{k=1}^{n} FSH_k \\cdot FB_k}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>Now only the last constraint remains, each item in the same row sharing the same height.<\/p>\n\n\n\n<p>The approach here will be to try to make each term constant independently of the item.<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mfrac><mrow><mi>F<\/mi><msub><mi>B<\/mi><mi>i<\/mi><\/msub><\/mrow><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><\/mrow><\/mfrac><annotation encoding=\"application\/x-tex\">\\frac{FB_i}{AR_i}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>That is the first term. We can put <math><msub><mi>FB<\/mi><mi>i<\/mi><\/msub><\/math> equal to <math><msub><mi>AR<\/mi><mi>i<\/mi><\/msub><\/math> so it simplifies with the denominator. Additionally, we can multiply it by a constant <em>\u03b1<\/em>:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>F<\/mi><msub><mi>B<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><mi>\u03b1<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">FB_i = AR_i \\cdot \\alpha<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>Plug the just-defined FB<sub>i<\/sub> into the first term:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mfrac><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><mi>\u03b1<\/mi><\/mrow><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><\/mrow><\/mfrac><mo>=<\/mo><mi>\u03b1<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">\\frac{AR_i \\cdot \\alpha}{AR_i} = \\alpha<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>Because <math><msub><mi>FB<\/mi><mi>i<\/mi><\/msub><\/math> is the width of the item before growing and shrinking happens, and because w<sub>i<\/sub> = <math><msub><mi>AR<\/mi><mi>i<\/mi><\/msub><\/math> \u2022 h<sub>i<\/sub> (from constraint A), we can see that <em>\u03b1<\/em> is the height of the item before growing and shrinking happens. And because it is the same for every item, we can conclude that for our layout to work, all the items must start at the same height.<\/p>\n\n\n\n<p>Rename <em>\u03b1<\/em> to <math><mi>CB<\/mi><\/math> (cross-basis) so:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>F<\/mi><msub><mi>B<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><mi>C<\/mi><mi>B<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">FB_i = AR_i \\cdot CB<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p><math><mi>IFS<\/mi><\/math> is the second term. If we think about it or look back at its expression, we can see that it&#8217;s already constant for items in a row.<\/p>\n\n\n\n<p>After plugging the just defined <math><msub><mi>FB<\/mi><mi>i<\/mi><\/msub><\/math> into the third term, it becomes: <\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mfrac><mrow><mi>F<\/mi><msub><mi>G<\/mi><mi>i<\/mi><\/msub><\/mrow><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><msubsup><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>k<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/msubsup><mi>F<\/mi><msub><mi>G<\/mi><mi>k<\/mi><\/msub><\/mrow><\/mfrac><mspace width=\"1em\"><\/mspace><mtext>&nbsp;or&nbsp;<\/mtext><mspace width=\"1em\"><\/mspace><mfrac><mrow><mi>F<\/mi><mi>S<\/mi><msub><mi>H<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><mi>C<\/mi><mi>B<\/mi><\/mrow><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><msubsup><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>k<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/msubsup><mi>F<\/mi><mi>S<\/mi><msub><mi>H<\/mi><mi>k<\/mi><\/msub><mo>\u22c5<\/mo><mi>A<\/mi><msub><mi>R<\/mi><mi>k<\/mi><\/msub><mo>\u22c5<\/mo><mi>C<\/mi><mi>B<\/mi><\/mrow><\/mfrac><mo>=<\/mo><mfrac><mrow><mi>F<\/mi><mi>S<\/mi><msub><mi>H<\/mi><mi>i<\/mi><\/msub><\/mrow><mrow><msubsup><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>k<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/msubsup><mi>F<\/mi><mi>S<\/mi><msub><mi>H<\/mi><mi>k<\/mi><\/msub><mo>\u22c5<\/mo><mi>A<\/mi><msub><mi>R<\/mi><mi>k<\/mi><\/msub><\/mrow><\/mfrac><mspace width=\"1em\"><\/mspace><mo form=\"prefix\" stretchy=\"false\">(<\/mo><mtext>&nbsp;for&nbsp;<\/mtext><mi>C<\/mi><mi>B<\/mi><mo>&gt;<\/mo><mn>0<\/mn><mo form=\"postfix\" stretchy=\"false\">)<\/mo><\/mrow><annotation encoding=\"application\/x-tex\">\\frac{F G_i}{A R_i \\cdot \\sum_{k=1}^n F G_k} \\quad \\text { or } \\quad \\frac{F S H_i \\cdot A R_i \\cdot C B}{A R_i \\cdot \\sum_{k=1}^n F S H_k \\cdot A R_k \\cdot C B}=\\frac{F S H_i}{\\sum_{k=1}^n F S H_k \\cdot A R_k} \\quad(\\text { for } C B&gt;0)<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>Depending on if <math><mi>IFS<\/mi><\/math> is positive or negative respectively.<\/p>\n\n\n\n<p>For positive <math><msub><mi>FB<\/mi><mi>i<\/mi><\/msub><\/math>, we can put <math><msub><mi>FG<\/mi><mi>i<\/mi><\/msub><\/math> equal to <math><msub><mi>AR<\/mi><mi>i<\/mi><\/msub><\/math> \u2022 <em>\u03b2<\/em>, with <em>\u03b2<\/em> being a constant of choice.<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>F<\/mi><msub><mi>G<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><mi>\u03b2<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">FG_i = AR_i \\cdot \\beta<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>Plug the just defined <math><msub><mi>FG<\/mi><mi>i<\/mi><\/msub><\/math> into the third term:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mfrac><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><mi>\u03b2<\/mi><\/mrow><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><msubsup><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>k<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/msubsup><mi>A<\/mi><msub><mi>R<\/mi><mi>k<\/mi><\/msub><mo>\u22c5<\/mo><mi>\u03b2<\/mi><\/mrow><\/mfrac><mo>=<\/mo><mfrac><mn>1<\/mn><mrow><msubsup><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>k<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/msubsup><mi>A<\/mi><msub><mi>R<\/mi><mi>k<\/mi><\/msub><\/mrow><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">\\frac{AR_i \\cdot \\beta}{AR_i \\cdot \\sum_{k=1}^{n} AR_k \\cdot \\beta} = \\frac{1}{\\sum_{k=1}^{n} AR_k}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p>We can see that <em>\u03b2<\/em> simplify away, and only remains 1 divided by the sum of aspect ratio, which is constant.<\/p>\n\n\n\n<p>In constraint B we put <math><msub><mi>FG<\/mi><mi>i<\/mi><\/msub><\/math> \u2265 1, that now translates to choosing a \u03b2 big enough such that <math><msub><mi>AR<\/mi><mi>i<\/mi><\/msub><\/math> \u2022 <em>\u03b2<\/em> \u2265 1 for every item.<\/p>\n\n\n\n<p>For negative <math><mi>IFS<\/mi><\/math>\n, we can push <math><msub><mi>FSH<\/mi><mi>i<\/mi><\/msub><\/math> = 1 so it&#8217;s constant and respects constraint B (<math><msub><mi>FSH<\/mi><mi>i<\/mi><\/msub><\/math> \u2265 1). <\/p>\n\n\n\n<p>The third term becomes:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mfrac><mn>1<\/mn><mrow><msubsup><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>k<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/msubsup><mi>A<\/mi><msub><mi>R<\/mi><mi>k<\/mi><\/msub><\/mrow><\/mfrac><annotation encoding=\"application\/x-tex\">\\frac{1}{\\sum_{k=1}^{n} AR_k}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Results<\/h2>\n\n\n\n<p>That&#8217;s it! We found some simple enough solutions. So to keep going here, for both positive and negative <math><mi>IFS<\/mi><\/math>:<\/p>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msub><mi>h<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mi>H<\/mi><mo>=<\/mo><mi>C<\/mi><mi>B<\/mi><mo>+<\/mo><mfrac><mrow><mi>I<\/mi><mi>F<\/mi><mi>S<\/mi><\/mrow><mrow><msubsup><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>k<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/msubsup><mi>A<\/mi><msub><mi>R<\/mi><mi>k<\/mi><\/msub><\/mrow><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">h_i = H = CB + \\frac{IFS}{\\sum_{k=1}^{n} AR_k}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><msub><mi>w<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mi>F<\/mi><msub><mi>B<\/mi><mi>i<\/mi><\/msub><mo>+<\/mo><mi>I<\/mi><mi>F<\/mi><mi>S<\/mi><mo>\u22c5<\/mo><mfrac><mrow><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><\/mrow><mrow><msubsup><mo movablelimits=\"false\">\u2211<\/mo><mrow><mi>k<\/mi><mo>=<\/mo><mn>1<\/mn><\/mrow><mi>n<\/mi><\/msubsup><mi>A<\/mi><msub><mi>R<\/mi><mi>k<\/mi><\/msub><\/mrow><\/mfrac><\/mrow><annotation encoding=\"application\/x-tex\">w_i = FB_i + IFS \\cdot \\frac{AR_i}{\\sum_{k=1}^{n} AR_k}<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>F<\/mi><msub><mi>G<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><mi>\u03b2<\/mi><mspace width=\"1em\"><\/mspace><mtext>such&nbsp;that<\/mtext><mspace width=\"1em\"><\/mspace><mi>F<\/mi><msub><mi>G<\/mi><mi>i<\/mi><\/msub><mo>\u2265<\/mo><mn>1<\/mn><mtext>&nbsp;for&nbsp;every&nbsp;<\/mtext><mi>i<\/mi><\/mrow><annotation encoding=\"application\/x-tex\">FG_i = AR_i \\cdot \\beta \\quad \\text{such that} \\quad FG_i \\geq 1 \\text{ for every } i<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>F<\/mi><mi>S<\/mi><msub><mi>H<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mn>1<\/mn><\/mrow><annotation encoding=\"application\/x-tex\">FSH_i = 1<\/annotation><\/semantics><\/math><\/div>\n\n\n\n<div class=\"wp-block-math\"><math display=\"block\"><semantics><mrow><mi>F<\/mi><msub><mi>B<\/mi><mi>i<\/mi><\/msub><mo>=<\/mo><mi>A<\/mi><msub><mi>R<\/mi><mi>i<\/mi><\/msub><mo>\u22c5<\/mo><mi>C<\/mi><mi>B<\/mi><mspace width=\"1em\"><\/mspace><\/mrow><annotation encoding=\"application\/x-tex\">FB_i = AR_i \\cdot CB \\quad <\/annotation><\/semantics><\/math><\/div>\n\n\n\n<p><math><mi>CB<\/mi><\/math> is a constant of choice, representing the cross-basis, meaning the height of the item before growing or shrinking happens.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The Intuition<\/h3>\n\n\n\n<p>All items start at the same height thanks to <code>flex-basis<\/code>.<\/p>\n\n\n\n<p>When <code>flex-grow<\/code> is tied to an items aspect ratio, wider items expand more in width than narrower ones. On the flip side, with <code>flex-shrink<\/code> set to 1, items shrink in proportion to their width, so wider items lose more space than narrow ones.<\/p>\n\n\n\n<p>Even though widths change at different rates, the height of all items changes evenly.<\/p>\n\n\n\n<p><strong>The result is that no matter the aspect ratio of the items, they end up the same height.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Demos<\/h2>\n\n\n\n<p>No wrapping:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_019cd8bf-ab8d-7e9f-9902-90f7a7c3f22a\" src=\"\/\/codepen.io\/editor\/anon\/embed\/019cd8bf-ab8d-7e9f-9902-90f7a7c3f22a?height=250&amp;theme-id=1&amp;slug-hash=019cd8bf-ab8d-7e9f-9902-90f7a7c3f22a&amp;default-tab=result\" height=\"250\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed 019cd8bf-ab8d-7e9f-9902-90f7a7c3f22a\" title=\"CodePen Embed 019cd8bf-ab8d-7e9f-9902-90f7a7c3f22a\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>With wrapping:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_019cd8fb-89d2-7572-9f54-aa1a3fa12758\" src=\"\/\/codepen.io\/editor\/anon\/embed\/019cd8fb-89d2-7572-9f54-aa1a3fa12758?height=450&amp;theme-id=1&amp;slug-hash=019cd8fb-89d2-7572-9f54-aa1a3fa12758&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed 019cd8fb-89d2-7572-9f54-aa1a3fa12758\" title=\"CodePen Embed 019cd8fb-89d2-7572-9f54-aa1a3fa12758\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>With limits:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_019cd903-7dc0-7225-bccc-91c0cf330740\" src=\"\/\/codepen.io\/editor\/anon\/embed\/019cd903-7dc0-7225-bccc-91c0cf330740?height=450&amp;theme-id=1&amp;slug-hash=019cd903-7dc0-7225-bccc-91c0cf330740&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed 019cd903-7dc0-7225-bccc-91c0cf330740\" title=\"CodePen Embed 019cd903-7dc0-7225-bccc-91c0cf330740\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<p>With images:<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_eYqavaP\" src=\"\/\/codepen.io\/anon\/embed\/eYqavaP?height=650&amp;theme-id=1&amp;slug-hash=eYqavaP&amp;default-tab=result\" height=\"650\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed eYqavaP\" title=\"CodePen Embed eYqavaP\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Flexbox has a very specific algorithm for determining how to deal with remaining (or lack of) space in a row. Let&#8217;s use actual math to understand it then apply it to a masonry layout.<\/p>\n","protected":false},"author":46,"featured_media":8948,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[156,7,344,123,165],"class_list":["post-8929","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-aspect-ratio","tag-css","tag-flexbox","tag-grid","tag-masonry"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2026\/03\/flexbox-aspect-ratio.jpg?fit=2000%2C1200&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/8929","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/46"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=8929"}],"version-history":[{"count":16,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/8929\/revisions"}],"predecessor-version":[{"id":8989,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/8929\/revisions\/8989"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/8948"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=8929"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=8929"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=8929"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}