{"componentChunkName":"component---src-templates-blog-post-js","path":"/blog/understanding-css-grid-and-flex","result":{"data":{"markdownRemark":{"html":"<p>This post is an attempt to better understand how CSS grid and flex work (individually and together, as it turns out). Like many others I tend to rely on a CSS framework (Bootstrap in my case) to do just about all content layout. CSS frameworks are great but it also important we appreciate what CSS brings out of the box with grid and flex in context of content layout. </p>\n<p>This is also an exploration on if, and when, we may be fine to not use a CSS framework and, instead, rely on CSS grid and flex for content layout.</p>\n<h2>What is CSS grid layout?</h2>\n<p>MDN starts on <a href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout\">CSS Grid Layout</a> with the following:</p>\n<blockquote>\n<p>CSS Grid Layout excels at dividing a page into major regions or defining the relationship in terms of size, position, and layer, between parts of a control built from HTML primitives.</p>\n</blockquote>\n<p>The definition can take you only so far, so ...</p>\n<h2><del>What can you do with CSS grid layout?</del></h2>\n<h2>How to do basic card grid layout?</h2>\n<p>We start with a bit of very simple HTML:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-jsx line-numbers\"><code class=\"language-jsx\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>html</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>head</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>css-layout.css<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>stylesheet<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>head</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>body</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h1</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">CSS Grid Layout basics - Cards</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h1</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>main</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n            </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>article<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h2</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Card #1 title</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h2</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Some text and description of different length</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>http://via.placeholder.com/300x300<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\">\n            </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n\n            </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>article<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h2</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Card #2 title</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h2</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Some text and description of different length</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>http://via.placeholder.com/300x300<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\">\n            </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n\n            </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>article<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h2</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Card #3 title, a much longer title as it turns out</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h2</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Some text and description of different length</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>http://via.placeholder.com/300x300<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\">\n            </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n\n            </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>article<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h2</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Card #4 title, with some more variants</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h2</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Some text and description of different length. Some text and description</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>http://via.placeholder.com/300x300<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\">\n            </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n\n            </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>article<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h2</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Card #5 title, with some more variants, should be enough</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h2</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Some text and description of different length. Some text and description</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n                </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>http://via.placeholder.com/300x300<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\">\n            </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n\n        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>main</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>body</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>html</span><span class=\"token punctuation\">></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p><code class=\"language-text\">main</code> is a container and we have a series of <code class=\"language-text\">div</code>s which represent our cards. With default Chrome rendering this looks like:</p>\n<p><img src=\"../images/20210924-cssgrid/Screen_Shot_2021-09-21_at_9.54.17_AM.png\" alt=\"Screen Shot 2021-09-21 at 9.54.17 AM.png\"></p>\n<p>A standard browser rendering of our HTML produces vertical cards stacked one after the other.</p>\n<p>Let's add some very basic CSS grid into this, just styling the <code class=\"language-text\">main</code> element for now (and some basic <code class=\"language-text\">body</code> level margins:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-jsx line-numbers\"><code class=\"language-jsx\"><span class=\"token operator\">*</span> <span class=\"token punctuation\">{</span>\n    box<span class=\"token operator\">-</span>sizing<span class=\"token punctuation\">:</span> border<span class=\"token operator\">-</span>box<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\nbody <span class=\"token punctuation\">{</span>\n    margin<span class=\"token punctuation\">:</span> <span class=\"token number\">10</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nmain <span class=\"token punctuation\">{</span>\n    display<span class=\"token punctuation\">:</span> grid<span class=\"token punctuation\">;</span>\n    grid<span class=\"token operator\">-</span>template<span class=\"token operator\">-</span>columns<span class=\"token punctuation\">:</span> <span class=\"token function\">repeat</span><span class=\"token punctuation\">(</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span>fr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    gap<span class=\"token punctuation\">:</span> <span class=\"token number\">10</span>px<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>This produces the following:</p>\n<p><img src=\"../images/20210924-cssgrid/Screen_Shot_2021-09-21_at_9.45.45_AM.png\" alt=\"Screen Shot 2021-09-21 at 9.45.45 AM.png\"></p>\n<p>Page rendered with basic css grid use produces a gallery layout with some alignment issues</p>\n<p>Not bad! We get three columns which equally expand (in width) to fill the available browser screen size. It is also responsive (... kinda ... but looks odd when stretched)! It is not production grade just yet, but certainly progress. Obviously we notice the odd alignment when the title is a bit long. </p>\n<h2>Making the grid responsive</h2>\n<p>We can get better responsive behaviour with the following adjustment to our css:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-jsx line-numbers\"><code class=\"language-jsx\">grid<span class=\"token operator\">-</span>template<span class=\"token operator\">-</span>columns<span class=\"token punctuation\">:</span> <span class=\"token function\">repeat</span><span class=\"token punctuation\">(</span>auto<span class=\"token operator\">-</span>fit<span class=\"token punctuation\">,</span> <span class=\"token function\">minmax</span><span class=\"token punctuation\">(</span><span class=\"token number\">300</span>px<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span>fr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>The important bit to note is the use of <code class=\"language-text\">auto-fit</code> as argument to the <code class=\"language-text\">repeat(...)</code> function. Instead of specifying \"3\" as 3 columns, now we are asking the browser to fit as many columns as it can, while making columns not smaller than 300px in width and equally distributing the available space. The resulting page looks as follows:</p>\n<p><img src=\"../images/20210924-cssgrid/autofit-grid-640p.gif\" alt=\"autofit-grid-640p.gif\"></p>\n<p>A more responsive grid, rendered with dynamic number of columns through use of <code class=\"language-text\">auto-fit</code></p>\n<p>Notice how we get a fairly decent responsive behaviour that goes from four columns down to one (my screen size did not allow for 5). I had to turn on inspector so that the browser would let me resize down to about 300px so that we can see all the \"breakpoints\".</p>\n<h2>Mixing CSS grid and Flex</h2>\n<p>While CSS grid is great and amazing and can do wonderful things it also exists alongside other great tools. Jen (linked in References below) offers guidance on combining grid with <code class=\"language-text\">flex</code> to achieve the responsive gallery layout we all want. </p>\n<p>Adding <code class=\"language-text\">flex</code> to our <code class=\"language-text\">div.article</code> is quite simple in this case:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-jsx line-numbers\"><code class=\"language-jsx\"><span class=\"token punctuation\">.</span>article <span class=\"token punctuation\">{</span>\n    display<span class=\"token punctuation\">:</span>flex<span class=\"token punctuation\">;</span>\n    flex<span class=\"token operator\">-</span>flow<span class=\"token punctuation\">:</span> column<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span></span></pre></div>\n<p>The <code class=\"language-text\">article</code> is a class defined on each of our <code class=\"language-text\">div</code> cards. By default, <code class=\"language-text\">display: flex</code> does a row-based layout of content, so that <code class=\"language-text\">flex-flow:column</code> is necessary to get it to do vertical layout.</p>\n<p>However, this change doesn't improve much on our previous state, it just adds some margins or paddings in each card as far as I can see:</p>\n<p><img src=\"../images/20210924-cssgrid/Screen_Shot_2021-09-21_at_3.05.00_PM.png\" alt=\"Screen Shot 2021-09-21 at 3.05.00 PM.png\"></p>\n<p>Adding <code class=\"language-text\">flex</code> to cards does not improve our gallery rendering</p>\n<p>The next thing is to make our <code class=\"language-text\">img</code> elements within the card go above the title, which is easily accomplished at <code class=\"language-text\">img</code> level thanks to flex display:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-jsx line-numbers\"><code class=\"language-jsx\">img <span class=\"token punctuation\">{</span>\n   order<span class=\"token punctuation\">:</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span></span></pre></div>\n<p>Doing <code class=\"language-text\">order: -1</code> makes the image element be the first within the card. The resulting page looks much better:</p>\n<p><img src=\"../images/20210924-cssgrid/Screen_Shot_2021-09-21_at_3.05.23_PM.png\" alt=\"Screen Shot 2021-09-21 at 3.05.23 PM.png\"></p>\n<p>Adding <code class=\"language-text\">order</code> on card <code class=\"language-text\">img</code> element makes the alignment much better</p>\n<p>The image is displayed above everything else and just because we're aligning the image first to the top of the card, the entire gallery layout seems a lot more sensible even without attempting to limit or constrain the other elements within the card in order to achieve a better, tighter alignment across all the elements.</p>\n<h3>Semantic HTML note</h3>\n<p>Note that our sample HTML looks as follows:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-jsx line-numbers\"><code class=\"language-jsx\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>article<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h2</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Card #1 title</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h2</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Some text and description of different length</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>img</span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>http://via.placeholder.com/300x200<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">alt</span><span class=\"token attr-value\"><span class=\"token punctuation\">=</span><span class=\"token punctuation\">\"</span>placeholder card image<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\">\n</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>The <code class=\"language-text\">h2</code> heading and the <code class=\"language-text\">p</code> description go above the image for better accessibility. However, once we use <code class=\"language-text\">flex</code> and <code class=\"language-text\">order</code> CSS on this layout (as described above) we visually still get images above headings while supporting better accessibility order of our HTML. </p>\n<h2><code class=\"language-text\">grid-template-columns</code> property</h2>\n<p><code class=\"language-text\">grid-template-columns</code> grid property describes the columns within the grid. Commonly, we then use <code class=\"language-text\">repeat</code> function to specify the repeating pattern for our columns in the grid. We have to be careful on how the values for columns are specified as they may produce some undesired overlaps when rendered.</p>\n<p>For example, if our image is 300x300px (as in the example HTML above), and we have the following column definition (notice the param for <code class=\"language-text\">minmax(...)</code>):</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-jsx line-numbers\"><code class=\"language-jsx\"><span class=\"token comment\">/* minmax value can lead to overlap if not in sync with content size */</span>\ngrid<span class=\"token operator\">-</span>template<span class=\"token operator\">-</span>columns<span class=\"token punctuation\">:</span> <span class=\"token function\">repeat</span><span class=\"token punctuation\">(</span>auto<span class=\"token operator\">-</span>fit<span class=\"token punctuation\">,</span> <span class=\"token function\">minmax</span><span class=\"token punctuation\">(</span><span class=\"token number\">200</span>px<span class=\"token punctuation\">,</span><span class=\"token number\">1</span>fr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span></span></pre></div>\n<p>The resulting grid will have an overlap as the <code class=\"language-text\">minmax</code> will allow for less space than the image width. It ends up looking as:</p>\n<p><img src=\"../images/20210924-cssgrid/gridlayout-overlap.png\" alt=\"gridlayout-overlap.png\"></p>\n<p>Overlap problems due to inappropriate use of <code class=\"language-text\">minmax()</code> and the content we have</p>\n<p>To explore what else can be done, we can control each column explicitly (instead of using <code class=\"language-text\">repeat(...)</code> in the <code class=\"language-text\">grid-template-columns</code>. As an example here is a definition of 3-column grid with columns being 100px, 100px and 300px in width, respectively:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-jsx line-numbers\"><code class=\"language-jsx\">main <span class=\"token punctuation\">{</span>\n    max<span class=\"token operator\">-</span>width<span class=\"token punctuation\">:</span><span class=\"token number\">10000</span>px<span class=\"token punctuation\">;</span>\n    display<span class=\"token punctuation\">:</span> grid<span class=\"token punctuation\">;</span>\n    grid<span class=\"token operator\">-</span>template<span class=\"token operator\">-</span>columns<span class=\"token punctuation\">:</span> <span class=\"token number\">100</span>px <span class=\"token number\">100</span>px <span class=\"token number\">300</span>px<span class=\"token punctuation\">;</span>\n    gap<span class=\"token punctuation\">:</span> <span class=\"token number\">10</span>px<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span><span></span><span></span><span></span><span></span><span></span></span></pre></div>\n<p>This produces a three column grid where <em>columns are fixed in size and do not change</em> in any way as we resize the browser. This looks as follows:</p>\n<p><img src=\"../images/20210924-cssgrid/minmax-1.png\" alt=\"minmax-1.png\"></p>\n<p>An example of a fixed column width rendering of our grid</p>\n<p>Note: I've removed the images from HTML to more easily illustrate the differences in sizing. If we had the images with the above CSS grid definition we would still have those annoying overlaps. I've also added a <code class=\"language-text\">border: 1px dotted red</code> on the <code class=\"language-text\">.article</code> to more easily show what's happening.</p>\n<p>We can specify the min and max values for each column, too:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-jsx line-numbers\"><code class=\"language-jsx\">grid<span class=\"token operator\">-</span>template<span class=\"token operator\">-</span>columns<span class=\"token punctuation\">:</span> <span class=\"token function\">minmax</span><span class=\"token punctuation\">(</span><span class=\"token number\">100</span>px<span class=\"token punctuation\">,</span><span class=\"token number\">100</span>px<span class=\"token punctuation\">)</span> <span class=\"token function\">minmax</span><span class=\"token punctuation\">(</span><span class=\"token number\">100</span>px<span class=\"token punctuation\">,</span><span class=\"token number\">200</span>px<span class=\"token punctuation\">)</span> <span class=\"token function\">minmax</span><span class=\"token punctuation\">(</span><span class=\"token number\">200</span>px<span class=\"token punctuation\">,</span><span class=\"token number\">300</span>px<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>This produces the following:</p>\n<p><img src=\"../images/20210924-cssgrid/minmax-2.png\" alt=\"minmax-2.png\"></p>\n<p>An example of a grid that allows for growth of 2nd and 3rd column, as defined in <code class=\"language-text\">minmax</code></p>\n<p>Resizing the browser grows the sizes of 2nd and 3rd columns up to the maximum value as specified in the <code class=\"language-text\">minmax(...)</code> function earlier. </p>\n<p>Finally, introducing dynamic resizing as a fraction of free space, the browser completely fills the available space. The CSS is:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-jsx line-numbers\"><code class=\"language-jsx\">grid<span class=\"token operator\">-</span>template<span class=\"token operator\">-</span>columns<span class=\"token punctuation\">:</span> <span class=\"token function\">minmax</span><span class=\"token punctuation\">(</span><span class=\"token number\">100</span>px<span class=\"token punctuation\">,</span><span class=\"token number\">100</span>px<span class=\"token punctuation\">)</span> <span class=\"token function\">minmax</span><span class=\"token punctuation\">(</span><span class=\"token number\">100</span>px<span class=\"token punctuation\">,</span><span class=\"token number\">1</span>fr<span class=\"token punctuation\">)</span> <span class=\"token function\">minmax</span><span class=\"token punctuation\">(</span><span class=\"token number\">200</span>px<span class=\"token punctuation\">,</span><span class=\"token number\">1</span>fr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>The <code class=\"language-text\">1fr</code> portion makes the 2nd and 3rd column further grow into available space in the browser as seen below:</p>\n<p><img src=\"../images/20210924-cssgrid/minmax-3.png\" alt=\"minmax-3.png\"></p>\n<p>An example of grid that grows to fill entire available space, due to use of <code class=\"language-text\">fr</code> fraction units</p>\n<p><code class=\"language-text\">minmax(...)</code> specifies the minimum and maximum sizes of a column. The first parameter is a minimum value a column should have and the 2nd one is the maximum. The tricky bit is when we express either of these with more complicated values. What I mean by that is that if we simply say</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-jsx line-numbers\"><code class=\"language-jsx\"><span class=\"token operator\">...</span> <span class=\"token function\">minmax</span><span class=\"token punctuation\">(</span><span class=\"token number\">100</span>px<span class=\"token punctuation\">,</span> <span class=\"token number\">300</span>px<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>This specifies minimum content size of 100px and maximum 300px. Very rigid and fixed.  </p>\n<p>However, if we do:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-jsx line-numbers\"><code class=\"language-jsx\"><span class=\"token operator\">...</span> <span class=\"token function\">minmax</span><span class=\"token punctuation\">(</span><span class=\"token number\">100</span>px<span class=\"token punctuation\">,</span> <span class=\"token number\">1</span>fr<span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>Now the lower limit is still 100px so content will never be less than that. But the upper limit is expressed with fractions which are flexible and depend on the available space in the browser. The browser figures out whatever space is available and distributes it across columns we defined with <code class=\"language-text\">fr</code> as maximum width, allowing them to equally share in that space. </p>\n<p>There are some keywords to be aware of too:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-jsx line-numbers\"><code class=\"language-jsx\"><span class=\"token operator\">...</span> <span class=\"token function\">minmax</span><span class=\"token punctuation\">(</span>min<span class=\"token operator\">-</span>content<span class=\"token punctuation\">,</span> <span class=\"token number\">300</span>px<span class=\"token punctuation\">)</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>In this case, the minimum size of a column will correspond to whatever the minimum size of the content contained in the column. So it could shrink quite a bit if we have very little in there. The maximum is fixed to 300px.</p>\n<p>Please <a href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/minmax()\">refer to MDN</a> for more details. </p>\n<h2><code class=\"language-text\">repeat()</code> function</h2>\n<p>There is a <code class=\"language-text\">repeat()</code> function that allows us to define column properties (such as width) which can then be repeated some number of times - either completely or a set number. The <code class=\"language-text\">repeat()</code> function can be put alongside other <code class=\"language-text\">minmax()</code>-based columns - thus allowing us to specify a repeating pattern as well as certain specific columns in the grid.</p>\n<p>As an example:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre style=\"counter-reset: linenumber NaN\" class=\"language-jsx line-numbers\"><code class=\"language-jsx\">grid<span class=\"token operator\">-</span>template<span class=\"token operator\">-</span>columns<span class=\"token punctuation\">:</span> <span class=\"token function\">repeat</span><span class=\"token punctuation\">(</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token function\">minmax</span><span class=\"token punctuation\">(</span><span class=\"token number\">100</span>px<span class=\"token punctuation\">,</span><span class=\"token number\">100</span>px<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token function\">minmax</span><span class=\"token punctuation\">(</span><span class=\"token number\">200</span>px<span class=\"token punctuation\">,</span><span class=\"token number\">1</span>fr<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code><span aria-hidden=\"true\" class=\"line-numbers-rows\" style=\"white-space: normal; width: auto; left: 0;\"><span></span></span></pre></div>\n<p>This repeats 3 columns of 100px in width and then adds a 4th column that is minimum 200px in width and will stretch to the available space. Resulting page looks like this:</p>\n<p><img src=\"../images/20210924-cssgrid/repeat-1.png\" alt=\"repeat-1.png\"></p>\n<p>Combining use of fixed width columns as well as <code class=\"language-text\">repeat</code> pattern columns in the same grid allows for defining fixed width to the layout together with more dynamic set of columns at the same time</p>\n<h2>CSS grid and media queries</h2>\n<p>CSS grid does not rely on media queries to achieve its responsive behaviour. It is the browser that does the heavy lifting and computation as it lays out content given the constraints defined for the grid. </p>\n<p>If we don't use media queries then, as far as I know, we can't have explicit control over content layout for particular screen sizes. That may be just fine in certain cases. For example, creating a gallery page of all the content that should simply automatically fill the available space of the screen we are dealing with. </p>\n<p>Obviously if we do care about particular screen sizes then we are back to square one and can introduce media queries first and then within that context either define multiple grids or, perhaps, start using the CSS framework of our choice.</p>\n<h2>Comparing CSS Grid layout with Bootstrap</h2>\n<p>An important part of CSS grid layout is that it does not deal with sizes of screens in the same way in which Bootstrap does. It does not rely on media queries at all. That also means that CSS grid layout does not recognize a mobile view and a desktop view and therefore can't adjust the rendering for that particular screen size. It simply <em>fills available space</em> by laying out the content following the rules defined for the grid. </p>\n<p>In contrast, Bootstrap allowed us to control what gets shown on a mobile phone-sized screen, IPAD and desktop through the use of media queries (which are implicitly used as we rely on Bootstrap's <code class=\"language-text\">md</code>, <code class=\"language-text\">lg</code>, etc screen size shortcut classes). Interestingly, Bootstrap 5 grid system relies on <code class=\"language-text\">flex</code> when building out the equivalent <a href=\"https://getbootstrap.com/docs/5.1/examples/album/\">album page example</a> (columns, cards and elements within cards are all <code class=\"language-text\">flex</code> display).</p>\n<p>The thing about grid layout is that it allows us to achieve a solid gallery view without the need to learn a CSS framework. </p>\n<p>Is that \"production ready\"? Close. Maybe not 100%. We get decent responsive behaviour, too. </p>\n<p>Do I try to not have a CSS framework at all? I doubt it. Chances are the frameworks are here to stay as we can get great default behaviour (albeit with some learning curve). But who hasn't spent time learning the framework of their choice by now?</p>\n<h2>References</h2>\n<ol>\n<li>Jen Simmons video on <a href=\"https://www.youtube.com/watch?v=dQHtT47eH0M\">Flexbox and CSS Grid together</a> for gallery layout got me started to look more into this</li>\n<li>MDN on <a href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout\">CSS Grid Layout</a></li>\n<li>MDN on <a href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns\">grid-template-columns</a></li>\n<li><a href=\"https://getbootstrap.com/docs/5.1/examples/album/\">Bootstrap album example</a> is a gallery (album) sample that does a similar layout, so worth investigating to contrast with the above</li>\n<li><code class=\"language-text\">flex-basis</code> <a href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox#the_flex-basis_property\">css property on MDN</a></li>\n<li><code class=\"language-text\">repeat()</code> <a href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/repeat()\">function on MDN</a></li>\n<li><code class=\"language-text\">minmax()</code> <a href=\"https://developer.mozilla.org/en-US/docs/Web/CSS/minmax()\">function on MDN</a></li>\n</ol>","excerpt":"This post is an attempt to better understand how CSS grid and flex work (individually and together, as it turns out). Like many others I tend to rely on a CSS…","frontmatter":{"date":"24 September, 2021","path":"/blog/understanding-css-grid-and-flex","title":"Understanding layouts with CSS grid and flex"},"fields":{"readingTime":{"text":"11 min read"}}}},"pageContext":{}}}