avatarThon Ly

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

20813

Abstract

t!</p><h2 id="00c6">Flexbox versus Grid</h2><p id="427f">Using Flexbox, let’s try to create <b>4 boxes</b> spread over <b>2 rows</b> and <b>2 columns</b> inside of <code><b>main</b></code>:</p><div id="c2c2"><pre><span class="hljs-section"><html></span> <span class="hljs-section"><head></span><span class="hljs-section"></head></span> <span class="hljs-section"><body></span> <span class="hljs-section"><header></span><span class="hljs-section"></header></span> <span class="hljs-section"><main></span>

<span class="hljs-section"></main></span> <span class="hljs-section"><footer></span><span class="hljs-section"></footer></span> <span class="hljs-section"></body></span> <span class="hljs-section"></html></span></pre></div><p id="50d2">Like before, let’s create a <code><b>section</b></code> element for <i>each</i> <b>box</b>:</p><div id="5052"><pre><span class="hljs-section"><html></span> <span class="hljs-section"><head></span><span class="hljs-section"></head></span> <span class="hljs-section"><body></span> <span class="hljs-section"><header></span><span class="hljs-section"></header></span> <span class="hljs-section"><main></span> <span class="hljs-section"><section></span><span class="hljs-section"></section></span> <span class="hljs-section"><section></span><span class="hljs-section"></section></span> <span class="hljs-section"><section></span><span class="hljs-section"></section></span> <span class="hljs-section"><section></span><span class="hljs-section"></section></span> <span class="hljs-section"></main></span> <span class="hljs-section"><footer></span><span class="hljs-section"></footer></span> <span class="hljs-section"></body></span> <span class="hljs-section"></html></span></pre></div><p id="bc86">To make these <b>boxes</b> behave as <b><i>flexboxes</i></b>, we set the <b>display</b> to <code>flex</code> in the <b><i>parent</i></b>:</p><div id="98db"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">7</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> dashed orange; <span class="hljs-attribute">display</span>: flex; }</pre></div><p id="0d14">And the <b>flex-flow</b> to <code>row</code> and <code>wrap</code> to make the boxes <b><i>wrap</i></b> to the <b><i>next</i> row</b>:</p><div id="5f50"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">7</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> dashed orange; <span class="hljs-attribute">display</span>: flex; <span class="hljs-attribute">flex-flow</span>: row wrap; }</pre></div><p id="d0c6">As for the <b><i>children</i></b> of <code><b>main</b></code>:</p><div id="a5f7"><pre><span class="hljs-selector-tag">section</span> {</pre></div><div id="47a0"><pre>}</pre></div><p id="3378">Let’s give them all a <b>flex</b> property of <code>1</code> for <b><i>grow</i></b>, <code>1</code> for <b><i>shrink</i></b>, and <code>200px</code> for the <b><i>basis</i></b> to make <i>space</i> for some boxes to <i>wrap</i> to the <i>next</i> row:</p><div id="2c92"><pre><span class="hljs-selector-tag">section</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">1</span> <span class="hljs-number">1</span> <span class="hljs-number">200px</span>; }</pre></div><blockquote id="1d4f"><p>Again, if these <b>flex</b> properties are still confusing, they will be covered in great detail in Unit 3.</p></blockquote><p id="087f">Finally, let’s give them all a <b>border</b> of <code>1px</code>, <code>solid</code> and <code>black</code> so we can visualize them:</p><div id="fb67"><pre><span class="hljs-selector-tag">section</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">1</span> <span class="hljs-number">1</span> <span class="hljs-number">200px</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid black; }</pre></div><p id="331a">It looks like we have achieved the <b>2x2 matrix</b> that we wanted:</p><figure id="c913"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*h8WaTD2E_ZqLhuxCuIIIEg.png"><figcaption><a href="https://codepen.io/thonly/pen/bGoJOEP?editors=1100">https://codepen.io/thonly/pen/bGoJOEP?editors=1100</a></figcaption></figure><p id="4ebf" type="7">However, there is a limitation.</p><p id="7501">Now try making the <b>viewport</b> <i>wider</i>:</p> <figure id="d194"> <div> <div> <img class="ratio" src="http://placehold.it/16x9"> <iframe class="" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcodepen.io%2Fthonly%2Fembed%2Fpreview%2FbGoJOEP%3Fdefault-tabs%3Dcss%252Cresult%26height%3D600%26host%3Dhttps%253A%252F%252Fcodepen.io%26slug-hash%3DbGoJOEP&amp;display_name=CodePen&amp;url=https%3A%2F%2Fcodepen.io%2Fthonly%2Fpen%2FbGoJOEP%3Feditors%3D1100&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=codepen" allowfullscreen="" frameborder="0" height="600" width="800"> </div> </div> </figure></iframe></div></div></figure><p id="e5a3">As you can see, <b>flex-wrap</b> <i>does not enforce</i> the <b><i>number</i></b> <b>of rows and columns</b>.</p><p id="75d2">In fact, <b>Flexbox</b> is intended to work really well whenever we want to lay out boxes in only <b><i>one</i> <i>direction</i></b>: <b>rows</b> <b>OR</b> <b>columns</b></p><p id="13a5">If we want to lay out boxes in <b><i>two</i> dimensions</b> that respect <i>both</i> <b>rows</b> <b>AND</b> <b>columns</b>, we should use <b>CSS Grid</b> instead.</p><p id="fb4e">Let’s demonstrate by refactoring our code to use <b>CSS Grid</b> instead of <b>Flexbox</b>.</p><p id="b318">On our <b><i>parent</i></b>, instead of <code>flex</code>, let’s set the <b>display</b> to <code>grid</code>:</p><div id="59b5"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">7</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> dashed orange; <span class="hljs-attribute">display</span>: grid; }</pre></div><p id="aa87">Instead of <b>flex-flow</b>, we can use <b>grid-template-rows </b>to set the <b><i>number</i> of rows</b>. Let’s create <b><i>two</i> rows</b> and give them <code>1</code> <b>fraction</b> <i>each</i>:</p><div id="72c8"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">7</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> dashed orange; <span class="hljs-attribute">display</span>: grid; <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr; }</pre></div><p id="0a1b">To set the <b><i>number</i> of columns,</b> we can use <b>grid-template-columns</b>. Let’s also create <b><i>two</i> columns</b> and give them <i>each</i> <code>1fr</code>:</p><div id="6795"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">7</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> dashed orange; <span class="hljs-attribute">display</span>: grid; <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr; <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr; }</pre></div><p id="5016">As for the <b><i>children</i></b> of <code><b>main</b></code>, the <b>flex</b> property is no longer necessary:</p><div id="0b80"><pre><span class="hljs-selector-tag">section</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">1</span> <span class="hljs-number">1</span> <span class="hljs-number">200px</span>; // delete <span class="hljs-attribute">border</span>: <span class="hljs-number">1px</span> solid black; }</pre></div><p id="aae6">As you can see, <b>CSS Grid</b> uses <code>fr</code> units which behave <b><i>exactly</i></b> <i>like</i> the <b><i>fraction</i></b> units of <b>Flexbox</b>.</p><div id="db8e"><pre><span class="hljs-attr">1fr</span> = <span class="hljs-number">1</span> fraction</pre></div><blockquote id="0a80"><p>The reason <b>CSS Grid</b> has the <code>fr</code> designation whereas <b>Flexbox</b> does not is because <b>CSS Grid</b> also allows <i>other</i> types of units too! (e.g., absolute units)</p></blockquote><p id="79ca">Now, let’s see what happens if we change the <b>viewport</b> <b><i>size</i></b> like before:</p><figure id="f3b7"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*VRapkqgOK2xsGzRwo8X_6g.png"><figcaption><a href="https://codepen.io/thonly/pen/qBmYOxa?editors=1100">https://codepen.io/thonly/pen/qBmYOxa?editors=1100</a></figcaption></figure><p id="429f">As you can see, when we use <b>CSS Grid</b>, an <i>invisible</i> <b>grid system</b> is created that <i>always respect</i> the <b><i>number</i></b> of <b>rows</b> <b>and</b> <b>columns</b>.</p><p id="9667">The finished Codepen:</p> <figure id="2aa8"> <div> <div> <img class="ratio" src="http://placehold.it/16x9"> <iframe class="" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcodepen.io%2Fthonly%2Fembed%2Fpreview%2FqBmYOxa%3Fdefault-tabs%3Dcss%252Cresult%26height%3D600%26host%3Dhttps%253A%252F%252Fcodepen.io%26slug-hash%3DqBmYOxa&amp;display_name=CodePen&amp;url=https%3A%2F%2Fcodepen.io%2Fthonly%2Fpen%2FqBmYOxa%3Feditors%3D1100&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=codepen" allowfullscreen="" frameborder="0" height="600" width="800"> </div> </div> </figure></iframe></div></div></figure><h2 id="161e">CSS Grid</h2><p id="8df5">Now that we know how useful a <b>grid system </b>can be, let’s study it in detail.</p><p id="34d4">Firstly, if all the <b>columns</b> or <b>rows</b> have <i>equal</i> lengths, we can use the <code>repeat()</code> <b>shortcut</b>:</p><div id="0158"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">7</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> dashed orange; <span class="hljs-attribute">display</span>: grid; <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(); <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr; }</pre></div><p id="7d6f">Then inside the parentheses, we indicate the <b><i>number</i></b> <b>of</b> <b>times</b>, and the <b><i>length</i></b> <b>for each one</b>:</p><div id="bf25"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">7</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> dashed orange; <span class="hljs-attribute">display</span>: grid; <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>fr); <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr; }</pre></div><p id="d8d5">Likewise, for the <b>rows</b>:</p><div id="fb8f"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">7</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> dashed orange; <span class="hljs-attribute">display</span>: grid; <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>fr); <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>fr); }</pre></div><p id="6873">Using this <b>shortcut</b>, we can easily create a <b>grid system</b> with <b>12 columns</b> and <b>12 rows</b> for example:</p><div id="d42a"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">7</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> dashed orange; <span class="hljs-attribute">display</span>: grid; <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">12</span>, <span class="hljs-number">1</span>fr); <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">12</span>, <span class="hljs-number">1</span>fr); }</pre></div><p id="f449">When we define <b>grid-template-columns</b> and <b>grid-template-rows</b>, we are defining an <b><i>explicit</i></b> <b>grid system</b> that has <b>column lines</b> and <b>row lines.</b></p><p id="f5cb">For example, inside <code><b>main</b></code>, the <b>column lines </b>are 1, 2, and 3 (from <b><i>left</i></b> to <b><i>right</i></b>). And the <b>row lines</b> are 1, 2, and 3 (from <b><i>top</i></b> to <b><i>bottom</i></b>).</p><figure id="c16c"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*DNWRvPtpNxYNunBJT1ePcQ.png"><figcaption><a href="https://codepen.io/thonly/pen/qBmYOxa?editors=1100">https://codepen.io/thonly/pen/qBmYOxa?editors=1100</a></figcaption></figure><blockquote id="013a"><p>To see the <b>grid lines</b> in <b><i>Chrome</i></b>, open <b>Developer Tools</b> and then click on the <b>Layout</b> tab and tick <b>Grid overlays</b>.</p></blockquote><p id="4645">We can use <b>these</b> <b>lines</b> to <i>place</i> the <b><i>children</i></b> of <code><b>main</b></code> <i>anywhere</i> on this grid.</p><p id="9416">For example, let’s place the <code><b>:first-child</b></code> at:</p><ul><li><b>grid-column</b>: from line <code>2</code> to line <code>3</code></li><li><b>grid-row</b>: from line <code>1</code> to line <code>2</code></li></ul><div id="6ea9"><pre><span class="hljs-selector-tag">section</span><span class="hljs-selector-pseudo">:first</span>-child { <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">2</span> / <span class="hljs-number">3</span>; <span class="hljs-attribute">grid-row</span>: <span class="hljs-number">1</span> / <span class="hljs-number">2</span> }</pre></div><p id="c0fa">To visualize it, let’s give it a <b>background-color</b> of <code>yellow</code>:</p><div id="5706"><pre><span class="hljs-selector-tag">section</span><span class="hljs-selector-pseudo">:first</span>-child { <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">2</span> / <span class="hljs-number">3</span>; <span class="hljs-attribute">grid-row</span>: <span class="hljs-number">1</span> / <span class="hljs-number">2</span>; <span class="hljs-attribute">background-color</span>: yellow; }</pre></div><p id="e5ef">If we want, we can even <b><i>span</i></b> it across <b>two rows</b>:</p><div id="db99"><pre><span class="hljs-selector-tag">section</span><span class="hljs-selector-pseudo">:first</span>-child { <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">2</span> / <span class="hljs-number">3</span>; <span class="hljs-attribute">grid-row</span>: <span class="hljs-number">1</span> / <span class="hljs-number">3</span>; <span class="hljs-attribute">background-color</span>: yellow; }</pre></div><p id="4a94">Instead of specifying a <b>row line</b>, we can also simply write <code>span 2</code>:</p><div id="33aa"><pre><span class="hljs-selector-tag">section</span><span class="hljs-selector-pseudo">:first</span>-child { <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">2</span> / <span class="hljs-number">3</span>; <span class="hljs-attribute">grid-row</span>: <span class="hljs-number">1</span> / span <span class="hljs-number">2</span>; <span class="hljs-attribute">background-color</span>: yellow; }</pre></div><p id="169f">If we prefer, there is <b>another method</b> we can use to <i>place</i> the <b><i>children</i></b> of <code><b>main</b></code> <i>anywhere</i> on our grid.</p><p id="ac7b">On the <b>top row</b>, let’s name the <b><i>left</i></b> <b>box</b> as <b>area</b> <code>one</code> and the <b><i>right</i></b> <b>box</b> as <b>area</b> <code>two</code>. On the <b>bottom</b> <b>row</b>, let’s name the <b><i>left</i></b> <b>box</b> as <b>area</b> <code>three</code> and the <b><i>right</i></b> <b>box</b> as <b>area</b> <code>four</code>.</p><p id="22d5">Then, on the <b><i>parent</i></b>, we can define the <b>grid-template-areas</b> as:</p><ul><li><code>“one two”</code> for the <b>top row</b></li><li><code>“three four</code>” for the <b>bottom row</b></li></ul><div id="b984"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">7</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> dashed orange; <span class="hljs-attribute">display</span>: grid; <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>fr); <span class="hljs-attribute">grid-template-rows</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>fr); <span class="hljs-attribute">grid-template-areas</span>: <span class="hljs-string">"one two"</span> <span class="hljs-string">"three four"</span>; }</pre></div><p id="db33">With <b>these</b> <b>areas</b> defined, let’s try placing the <code>:last-child</code> at <b>grid-area</b> <code>two</code>:</p><div id="ea32"><pre><span class="hljs-selector-tag">section</span><span class="hljs-selector-pseudo">:last-child</span> { <span class="hljs-attribute">grid-area</span>: two; }</pre></div><p id="4a57">To visualize it, let’s give it a <b>background-color</b> of <code>violet</code>:</p><div id="f9fe"><pre><span class="hljs-selector-tag">section</span><span class="hljs-selector-pseudo">:last-child</span> { <span class="hljs-attribute">grid-area</span>: two; <span class="hljs-attribute">background-color</span>: violet; }</pre></div><p id="0edf">As you can see, this places the <code>:last-child</code> on top of the <code>:first-child</code>. The reason is because by default their <b>stacking order</b> follows their <b>order in the HTML Tree</b>.</p><div id="7790"><pre>HTML Tree <span class="hljs-keyword">Order</span> <span class="hljs-title">=> Stacking</span> Order</pre></div><p id="5424">If we want, we can change their <b>stacking order</b> by using the <b>z-index</b> which is <code>0</code> by default:</p><div id="57b9"><pre><span class="hljs-selector-tag">section</span><span class="hljs-selector-pseudo">:first</span>-child { <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">2</span> / <span class="hljs-number">3</span>; <span class="hljs-attribute">grid-row</span>: <span class="hljs-number">1</span> / span <span class="hljs-number">2</span>; <span class="hljs-attribute">background-color</span>: yellow; <span class="hljs-attribute">z-index</span>: <span class="hljs-number">0</span>; }</pre></div><div id="a3de"><pre><span class="hljs-selector-tag">section</span><span class="hljs-selector-pseudo">:last-child</span> { <span class="hljs-attribute">grid-area</span>: two; <span class="hljs-attribute">background-color</span>: violet; <span class="hljs-attribute">z-index</span>: <span class="hljs-number">0</span>; }</pre></div><p id="b546">If we want the <code>:first-child</code> to be on <b>top</b>, we simply give it a <i>higher</i> <b>z-index</b>.</p><p id="8d56">For example: <code>1</code></p><div id="3a7c"><pre><span class="hljs-selector-tag">section</span><span class="hljs-selector-pseudo">:first</span>-child { <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">2</span> / <span class="hljs-number">3</span>; <span class="hljs-attribute">grid-row</span>: <span class="hljs-number">1</span> / span <span class="hljs-number">2</span>; <span class="hljs-attribute">background-color</span>: yellow; <span c

Options

lass="hljs-attribute">z-index</span>: <span class="hljs-number">1</span>; }</pre></div><div id="3eff"><pre><span class="hljs-selector-tag">section</span><span class="hljs-selector-pseudo">:last-child</span> { <span class="hljs-attribute">grid-area</span>: two; <span class="hljs-attribute">background-color</span>: violet; <span class="hljs-attribute">z-index</span>: <span class="hljs-number">0</span>; }</pre></div><p id="fb5b">But let’s make the <code>:last-child</code> on <b>top</b> instead by giving it an even <i>greater</i> <b>z-index</b>: <code>2</code></p><div id="6353"><pre><span class="hljs-selector-tag">section</span><span class="hljs-selector-pseudo">:first</span>-child { <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">2</span> / <span class="hljs-number">3</span>; <span class="hljs-attribute">grid-row</span>: <span class="hljs-number">1</span> / span <span class="hljs-number">2</span>; <span class="hljs-attribute">background-color</span>: yellow; <span class="hljs-attribute">z-index</span>: <span class="hljs-number">1</span>; }</pre></div><div id="a793"><pre><span class="hljs-selector-tag">section</span><span class="hljs-selector-pseudo">:last-child</span> { <span class="hljs-attribute">grid-area</span>: two; <span class="hljs-attribute">background-color</span>: violet; <span class="hljs-attribute">z-index</span>: <span class="hljs-number">2</span>; }</pre></div><p id="5cc0">Moreover, if we want a <b>grid system</b> that is <i>more</i> <i>flexible</i>, we can define an <b><i>implicit</i></b> <b>grid system</b> by <i>removing</i> one dimension: <b>grid-template-columns</b> or <b>grid-template-rows</b></p><p id="ebb2">For example, let’s remove <b>grid-template-rows</b>. In its place, we can define a <b>grid-auto-flow</b> and set it to <code>row</code>:</p><div id="0216"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">7</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> dashed orange; <span class="hljs-attribute">display</span>: grid; <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>fr); <span class="hljs-attribute">grid-auto-flow</span>: row; <span class="hljs-attribute">grid-template-areas</span>: <span class="hljs-string">"one two"</span> <span class="hljs-string">"three four"</span>; }</pre></div><p id="d6bf">This makes the <code>row</code> behave like <b>flex-wrap</b>!</p><p id="9814">We can also specify a <b>height</b> for these <i>automatic</i> rows using <b>grid-auto-rows</b>.</p><p id="f71d">For example: <code>100px</code></p><div id="4a7e"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">7</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> dashed orange; <span class="hljs-attribute">display</span>: grid; <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>fr); <span class="hljs-attribute">grid-auto-flow</span>: row; <span class="hljs-attribute">grid-auto-rows</span>: <span class="hljs-number">100px</span>; <span class="hljs-attribute">grid-template-areas</span>: <span class="hljs-string">"one two"</span> <span class="hljs-string">"three four"</span>; }</pre></div><p id="139f">Finally, in <i>between</i> <i>the columns</i>, we can specify a <b>gap</b> using <b>grid-column-gap</b>.</p><p id="5705">For example: <code>5px</code></p><div id="a7f0"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">7</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> dashed orange; <span class="hljs-attribute">display</span>: grid; <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>fr); <span class="hljs-attribute">grid-auto-flow</span>: row; <span class="hljs-attribute">grid-auto-rows</span>: <span class="hljs-number">100px</span>; <span class="hljs-attribute">grid-column</span>-<span class="hljs-attribute">gap</span>: <span class="hljs-number">5px</span>; <span class="hljs-attribute">grid-template-areas</span>: <span class="hljs-string">"one two"</span> <span class="hljs-string">"three four"</span>; }</pre></div><p id="3839">Likewise, we can specify a <b>gap</b> <i>between the rows</i> as well using <b>grid-row-gap</b>.</p><p id="d951">For example: <code>10px</code></p><div id="5f8a"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">flex</span>: <span class="hljs-number">7</span>; <span class="hljs-attribute">border</span>: <span class="hljs-number">5px</span> dashed orange; <span class="hljs-attribute">display</span>: grid; <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">2</span>, <span class="hljs-number">1</span>fr); <span class="hljs-attribute">grid-auto-flow</span>: row; <span class="hljs-attribute">grid-auto-rows</span>: <span class="hljs-number">100px</span>; <span class="hljs-attribute">grid-column</span>-<span class="hljs-attribute">gap</span>: <span class="hljs-number">5px</span>; <span class="hljs-attribute">grid-row</span>-<span class="hljs-attribute">gap</span>: <span class="hljs-number">10px</span>; <span class="hljs-attribute">grid-template-areas</span>: <span class="hljs-string">"one two"</span> <span class="hljs-string">"three four"</span>; }</pre></div><figure id="2141"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*QTaxfz0oIiDqieikCmDb_g.png"><figcaption><a href="https://codepen.io/thonly/pen/qBmyaZN?editors=1100">https://codepen.io/thonly/pen/qBmyaZN?editors=1100</a></figcaption></figure><p id="edb3">The finished <a href="https://codepen.io/thonly/pen/qBmyaZN?editors=1100">Codepen</a>:</p> <figure id="381b"> <div> <div> <img class="ratio" src="http://placehold.it/16x9"> <iframe class="" src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fcodepen.io%2Fthonly%2Fembed%2Fpreview%2FqBmyaZN%3Fdefault-tabs%3Dcss%252Cresult%26height%3D600%26host%3Dhttps%253A%252F%252Fcodepen.io%26slug-hash%3DqBmyaZN&amp;display_name=CodePen&amp;url=https%3A%2F%2Fcodepen.io%2Fthonly%2Fpen%2FqBmyaZN%3Feditors%3D1100&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=codepen" allowfullscreen="" frameborder="0" height="600" width="800"> </div> </div> </figure></iframe></div></div></figure><h1 id="6e3b">Summary</h1><p id="57d0"><b>Flexbox</b> is amazing when we want to <i>align</i> <b><i>children</i></b> elements along <b>one axis</b>. But if we want to <i>align</i> them along <b>both axes</b>, it is better to use <b>CSS Grid</b> to create an <i>invisible</i> <b>grid system</b> upon which we can place the <b><i>children</i></b> elements.</p><figure id="204b"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*3Xg8y8d3qjalI2gaNZlMHw.png"><figcaption><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout#the_implicit_and_explicit_grid">https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout#the_implicit_and_explicit_grid</a></figcaption></figure><p id="275c">To create a <b>grid system</b>, we set the <b>display</b> to <code>grid</code> on the <b><i>parent</i></b> element.</p><div id="be0b"><pre><span class="hljs-selector-tag">main</span> { <span class="hljs-attribute">display</span>: grid; }</pre></div><p id="78aa">Then, we can define the <b><i>grid</i></b><i> <b>tracks</b></i> using <b>grid-template-rows</b> and <b>grid-template-columns</b>.</p><figure id="677d"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*t9wWbFYz8E4OWjL_.png"><figcaption><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_grid_track.png">https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_grid_track.png</a></figcaption></figure><p id="1dc8"><b>These tracks</b> can be defined using <i>any</i> <b>length units</b>. If we want, we can also use <b><i>fraction</i></b> <b>units</b> which behave like <b>flexboxes</b> <b>that <i>expand</i> to fill the <i>parent</i> container.</b></p><div id="844e"><pre><span class="hljs-attribute">grid</span>-template-columns: <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr <span class="hljs-number">1</span>fr;</pre></div><blockquote id="2c54"><p>Like <b>flexboxes</b>, we can think of <code>fr</code> units as <b><i>slices</i></b> of a <b>whole</b> <b>pizza</b>. We are free to cut up the <b>whole</b> <b>pizza</b> into <b><i>as many equal fractions</i></b> as we desire.</p></blockquote><p id="b094">If the <b>track sizes</b> are <b><i>repetitive</i></b>, we can use the <code>repeat()</code> shortcut:</p><div id="584a"><pre><span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">3</span>, <span class="hljs-number">1</span>fr);</pre></div><p id="d388">When we define <b>grid-template-columns</b> and <b>grid-template-rows</b>, the <b>tracks</b> created are part of the <b><i>explicit</i></b> <b>grid</b>.</p><p id="8d75">If <i>one axis</i> <i>is not defined</i>, its <b>corresponding</b> <b>tracks</b> may still be created as part of the <b><i>implicit</i></b> <b>grid</b>.</p><p id="b9ca">These <b>implicit</b> <b>tracks</b> can be controlled using:</p><ul><li><b>grid-auto-flow</b></li><li><b>grid-auto-rows</b></li><li><b>grid-auto-columns</b></li></ul><p id="8de8">As such, they behave like <b>flex-wrap</b>.</p><p id="0b41">The <b>grid lines</b> are <i>numbered</i> from <b><i>left</i></b> to <b><i>right</i></b>, and <b><i>top</i></b> to <b><i>bottom</i></b>:</p><figure id="a60d"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*kRO9RlkiReYmhSOW.png"><figcaption><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_diagram_numbered_grid_lines.png">https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_diagram_numbered_grid_lines.png</a></figcaption></figure><p id="63be">This makes it possible to <i>place</i> <b><i>children</i></b> <b>elements</b> <i>anywhere</i> on the <b>grid</b> by using <b>grid-column</b> and <b>grid-row</b>.</p><p id="d623">We can <i>place</i> <b>elements</b> in <i>any</i> <b>grid cell</b>:</p><figure id="e4d9"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*_kifNIKdINwm4W0P.png"><figcaption><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_grid_cell.png">https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_grid_cell.png</a></figcaption></figure><p id="8b18">Or, we can <b><i>span</i></b> them across <b><i>multiple</i></b> <b>cells</b>:</p><figure id="d19d"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*UtT0Qbfd4gRs9fLF.png"><figcaption><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_grid_area.png">https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_grid_area.png</a></figcaption></figure><p id="328d"><b>Gutters</b> are the <i>gaps</i> in between the <b>track rows</b> and <b>track columns</b>.</p><p id="a926">To create them, we can use <b>row-gap</b> and <b>column-gap</b>.</p><div id="f72b"><pre><span class="hljs-attribute">column-gap</span>: <span class="hljs-number">10px</span>; <span class="hljs-attribute">row-gap</span>: <span class="hljs-number">1em</span>;</pre></div><p id="2dcf"><b><i>Multiple</i> elements</b> can be <i>placed</i> on the <b><i>same</i> cell</b>.</p><figure id="7458"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*214XFtofDgO5qg_T.png"><figcaption><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_nested_grids_in_flow.png">https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_nested_grids_in_flow.png</a></figcaption></figure><p id="8216">When this happens, the elements <b><i>stack</i></b> on top of one another <b>according to their order in the HTML Tree</b>.</p><p id="e116">To change this <b><i>default</i> order</b>, we can use the <b>z-index</b>.</p><div id="d888"><pre><span class="hljs-attribute">z-index</span>: <span class="hljs-number">2</span>;</pre></div><blockquote id="193c"><p>Don’t worry if CSS Grid is still confusing. We will study it some more in Unit 3!</p></blockquote><h1 id="3a95">Concept Quiz</h1><p id="c1ed">Take my <a href="https://frontend.siliconwat.com/#learn-chapter15"><b>Programming Concept Quiz</b></a> to check your understanding! For every correct choice, you will earn <b>SW Coins</b> which you can redeem for <b><i>coupons</i></b> towards the purchase of any of my <a href="https://siliconwat.com">Udemy courses</a>!</p><p id="827f"><b><i>Sample</i></b> Quiz Questions for <b>Lesson 15</b>:</p><h2 id="8ad0">Question 1:</h2><p id="dee3">Which <b>display</b> type is best for aligning elements that respect <b>both axes</b>?</p><ol><li>inline-block</li><li>block</li><li>flex</li><li>grid</li></ol><h2 id="3002">Question 2:</h2><p id="51e7">Which <b>grid</b> property is NOT declared on the <b><i>parent</i></b> element?</p><ol><li>display</li><li>grid-template-rows</li><li>grid-template-columns</li><li>grid-auto-flow</li><li>grid-auto-rows</li><li>grid-auto-columns</li><li>z-index</li><li>grid-row-gap</li><li>grid-column-gap</li></ol><h2 id="4f21">Question 3:</h2><p id="8612">Which <b>grid</b> property is NOT declared on the <b><i>children</i></b> elements?</p><ol><li>grid-column</li><li>grid-row</li><li>grid-area</li><li>grid-template-areas</li></ol><h2 id="e5b3">Question 4:</h2><p id="93ef"><code>repeat(4, 2fr)</code> is <i>equal</i> to:</p><ol><li>1fr 1fr</li><li>2fr 2fr</li><li>2fr 2fr 2fr 2fr</li><li>1fr 1fr 1fr 1fr</li></ol><h2 id="1f82">Question 5:</h2><p id="4db2">Which <b>grid</b> property does NOT create an <b><i>explicit</i></b> <b>grid</b>?</p><ol><li>grid-template-rows</li><li>grid-template-columns</li><li>grid-auto-flow</li></ol><h2 id="d5ef">Question 6:</h2><p id="0b5f">Which <b>grid</b> property does NOT relate to the <b><i>implicit</i></b> <b>grid</b>?</p><ol><li>grid-auto-row</li><li>grid-auto-columns</li><li>grid-template-areas</li></ol><h2 id="98b9">Question 7:</h2><p id="d343"><b>Grid lines</b> are <i>numbered</i> from:</p><ol><li>right to left, bottom to top</li><li>left to right, bottom to top</li><li>right to left, top to bottom</li><li>left to right, top to bottom</li></ol><h2 id="3ef5">Question 8:</h2><p id="d8e8">We CANNOT <i>span</i> elements across <i>multiple</i> <b>grid cells</b>?</p><ol><li>True</li><li>False</li></ol><h2 id="2294">Question 9:</h2><p id="d0ae">A <i>lower</i> <b>z-index</b> will make the element appear on the:</p><ol><li>bottom</li><li>top</li></ol><h2 id="7d64">Question 10:</h2><p id="a136"><b>grid-auto-flow</b> behaves like <b>flex-wrap</b>.</p><ol><li>True</li><li>False</li></ol><h2 id="3391">Question 11:</h2><p id="8319"><code>fr</code> <b>units</b> behave like <b>flexboxes</b>.</p><ol><li>True</li><li>False</li></ol><h2 id="6006">Question 12:</h2><p id="33e7">Only <b><i>direct</i></b> <b>children</b> can be placed on the <b>grid system</b> created by the <b><i>parent</i></b> element.</p><ol><li>True</li><li>False</li></ol><p id="3e84"><a href="https://frontend.siliconwat.com/#learn-chapter15">Programming Concept Quiz for Chapter 15</a></p><h1 id="df1d">Coding Exercises</h1><p id="28d1">Check out my <a href="https://frontend.siliconwat.com/#practice-chapter15"><b>Interactive Coding Exercises</b></a> to put to practice what you have learned! There, you will also find <b><i>interactive hints</i></b> to help you understand<i> each line of code. </i>Likewise, for every correct solution, you will earn <b>SW Coins</b> which you can redeem for <b><i>coupons</i></b> towards the purchase of any of my <a href="https://siliconwat.com">Udemy courses</a>!</p><p id="b26c"><a href="https://frontend.siliconwat.com/#practice-chapter15">Interactive Coding Exercises for Chapter 15</a></p><h1 id="da70">Syntax Flashcards</h1><p id="ebac">Review what you have learned by playing my <a href="https://frontend.siliconwat.com/#review-chapter15"><b>Syntax Flashcard Game</b></a>! These flashcards are designed to help you <b><i>commit to memory</i></b> all the <b><i>new</i></b> <b>code</b> <b>syntaxes</b> you learned in this lesson. Likewise, for every correct answer, you will earn <b>SW Coins</b> which you can redeem for <b><i>coupons</i></b> towards the purchase of any of my <a href="https://siliconwat.com">Udemy courses</a>!</p><p id="20ad"><a href="https://frontend.siliconwat.com/#review-chapter15">Syntax Flashcard Game for Chapter 15</a></p><h1 id="0410">Next Steps</h1><p id="f433">Congrats on completing <b>Unit 2:</b> <b>Lesson 10 of 13</b>! 🎉</p><div id="9f05"><pre><span class="hljs-attribute">Unit</span> <span class="hljs-number">1</span>: <span class="hljs-number">100</span>% Completed <span class="hljs-attribute">Unit</span> <span class="hljs-number">2</span>: <span class="hljs-number">77</span>% Completed <span class="hljs-attribute">Unit</span> <span class="hljs-number">3</span>: <span class="hljs-number">0</span>% Completed <span class="hljs-attribute">Unit</span> <span class="hljs-number">4</span>: <span class="hljs-number">0</span>% Completed <span class="hljs-attribute">Unit</span> <span class="hljs-number">5</span>: <span class="hljs-number">0</span>% Completed <span class="hljs-attribute">Bonus</span> Unit <span class="hljs-number">6</span>: <span class="hljs-number">0</span>% Completed <span class="hljs-attribute">Bonus</span> Unit <span class="hljs-number">7</span>: <span class="hljs-number">0</span>% Completed</pre></div><div id="5403"><pre><span class="hljs-attribute">Overall</span> Progress: <span class="hljs-number">15</span>% Completed</pre></div><p id="23f1"><a href="https://frontend.siliconwat.org">Join Remote Frontend Cohort Program</a></p><h2 id="c823">Next Lesson</h2><p id="078f">Since we can now <i>effortless</i> <i>create</i> any <b>page layout</b> of our choosing, we are ready to <i>add</i> <b><i>actual</i> content</b>! In the next lesson, we will begin by learning how to add <b>texts</b>. Sounds simple enough on the surface, but we will also look <b><i>under the surface</i></b>. Believe it or not, <b>plain texts</b> are HTML <b>elements</b> too except they are just <b><i>tag-less</i></b>. On the DOM Tree, they exist as <code><b>textNodes</b></code>. In the next lesson, we will use <b>JavaScript</b> to help us study these <code><b>textNodes</b></code> in detail. Texts are so ubiquitous (especially on a platform like Medium) that they seem trivial, but <i>nothing is further from the truth</i>. Mastering <code><b>textNodes</b></code> will help us <i>glimpse</i> the incredible technology powering a writing platform like Medium!</p><p id="53ec"><b><a href="https://readmedium.com/chapter-16-html-text-nodes-in-javascript-cc08da2a1125">Chapter 16: HTML Text Nodes in JavaScript</a></b></p><p id="f20a"><b><a href="https://frontend.siliconwat.com">Table of Contents</a></b></p><div id="f916" class="link-block"> <a href="https://medium.com/@thonly/membership"> <div> <div> <h2>Join Medium with my referral link — Thon Ly</h2> <div><h3>As a Medium member, a portion of your membership fee goes to writers you read, and you get full access to every story…</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*gOmGdkmkAHn0xYBV)"></div> </div> </div> </a> </div><blockquote id="0a07"><p>When you use my <a href="https://medium.com/@thonly/membership">referral link</a> above 👆 to become a Medium member, <b>all proceeds</b> will be donated towards the construction of the <a href="https://siliconwat.org">Silicon Wat Campus</a> for children in <b>Ukraine</b> and <b>Cambodia</b> ❤️</p></blockquote></article></body>

Chapter 15: Responsive Layouts with CSS Grid

A Complete Frontend Developer Textbook for Beginners (2023 Edition)

This is the textbook version of Lesson 15 of 100 from the Udemy video course: A Complete Frontend Developer Course for Beginners

Chapter 14: Responsive Layouts with CSS Flexbox

Table of Contents

Overview

This lesson covers the following HTML tags, CSS properties, and JavaScript commands for the first time:

HTML

None.

CSS

  1. grid-template-rows
  2. grid-template-columns
  3. grid-template-areas
  4. grid-row-gap
  5. grid-column-gap
  6. grid-auto-flow
  7. grid-auto-rows
  8. grid-auto-columns
  9. grid-row
  10. grid-column
  11. grid-area
  12. z-index
  13. :nth-child()
  14. repeat()

JS

None.

This lesson begins with this Codepen. Code along with me to increase retention!

Lecture

Before diving deep into CSS Grid, let’s review Flexbox one more time. This time around, let’s complete the Holy Grail as depicted:

https://en.wikipedia.org/wiki/Holy_grail_(web_design)#/media/File:HolyGrail.svg

Fully mastering Flexbox will help us segue seamlessly into CSS Grid!

Holy Grail with Flexbox

As depicted in the Holy Grail, the main section has three subsections. Therefore, let’s add another section subsection to main:

HTML Window:
<html>
 <head></head>
 <body>
  <header></header>
  <main>
   <section></section>
   <section></section>
   <section></section>
  </main>
  <footer></footer>
 </body>
</html>

To go fullscreen, let’s remove the default margin in body like usual:

CSS Window:
body {
 margin: 0;
}

To follow the best practice, let’s also define the dimensions of our fullscreen here at the highest parent:

body {
 margin: 0;
 width: 100vw;
 height: 100vh;
}

This way, all children elements of body can simply use relative units (to the body) like percentages.

header {
 width: 100%;
 height: 20%;
}
main {
 width: 100%;
 height: 70%;
}
footer {
 width: 100%;
 height: 10%;
}

This is a best practice because one simple change at the top will trickle down to all the descendants.

Even better than percentages, let’s use flexboxes instead! To do this, first we need to set the display to flex on the parent:

body {
 margin: 0;
 width: 100vw;
 height: 100vh;
 display: flex;
}

Then we set the flex-direction to column:

body {
 margin: 0;
 width: 100vw;
 height: 100vh;
 display: flex;
 flex-direction: column;
}

Now, we’re ready to use flexboxes instead of percentages.

Remember: Flexbox uses fraction units to make partitioning all the available space of the parent easy and intuitive.

header {
 flex: 1;
}
main {
 flex: 1;
}
footer {
 flex: 1;
}

With a flex value of 1, for example, right away, without needing to declare the width and height, all the children elements will expand to fill up the parent container equally and automatically.

To make the children take up the same amount as the percentages, we can partition them as follows:

header {
 flex: 2;
}
main {
 flex: 7;
}
footer {
 flex: 1;
}

A flex value of 1 (for example) is actually a shorthand for a flex-grow of 1.

How did we get these numbers?

To use an analogy, when we turn on flexbox, it’s like we’ve been given a whole pizza.

Parent Container => Whole Pizza

We can cut up this pizza into as many equal slices as we want!

Fraction units are like these equal slices of pizza!

Fractions => Slices

In our example, we simply choose to divide our pizza into 10 equal slices:

Total: 2 + 7 + 1 = 10

If the header takes up 2 slices, how much did it take from the total?

2 / 10 = 20%

If the main takes up 7 slices, how much did it take from the total?

7 / 10 = 70%

And if the footer takes up 1 slice, how much did it take from the total?

1 / 10 = 10%

Hence, the fractions we use here are equivalent to the percentages we used at the beginning.

Back to our example, let’s give each section of the body a border like before so we can visualize them:

header {
 flex: 2;
 border: 5px dashed green;
}
main {
 flex: 7;
 border: 5px dashed orange;
}
footer {
 flex: 1;
 border: 5px dashed blue;
}

Unlike before, however, a box-sizing of border-box is no longer necessary. As we have witnessed, flexboxes expand to fill the parent container automatically.

🎉 The sections look great, and the CSS code is a lot cleaner than before too!

Now, let’s create the subsections!

Again, to make these subsections behave as flexboxes, we need to set the display to flex on the parent:

main {
 flex: 7;
 border: 5px dashed orange;
 display: flex;
}

But this time, let’s set the flex-direction to row:

main {
 flex: 7;
 border: 5px dashed orange;
 display: flex;
 flex-direction: row;
}

Like before, let’s make the left section element the :first-child:

section:first-child {
 
}

And let’s make the right section element the :last-child:

section:last-child {
 
}

What about the middle section element?

<html>
 <head></head>
 <body>
  <header></header>
  <main>
   <section></section>
   <section></section>
   <section></section>
  </main>
  <footer></footer>
 </body>
</html>

How do we select it with CSS code?

We can use another pseudo-class called :nth-child():

section:nth-child() {
}

Then inside the parentheses, we specify which child we want. In our case, it’s the second child:

section:nth-child(2) {

}

If we wanted, we could also use this pseudo-class to select the :first-child using :nth-child(1) and the :last-child as :nth-child(3). Again, we will study pseudo-classes in great detail in Unit 3.

How should we partition all the available space of main amongst its subsections?

Again, we have total freedom to divide the parent container into as many equal fractions as we like, but for simplicity, let’s imagine again that there are 10 fractions total.

Let’s give the left subsection 2 fractions and a background-color of yellow so we can see it:

section:first-child {
 flex: 2;
 background-color: yellow;
}

Let’s also give the right subsection 2 fractions but a background-color of purple so we can see it:

section:last-child {
 flex: 2;
 background-color: purple;
}

Finally, let’s give the middle subsection the remaining fractions and a background-color of red so we can see it:

section:nth-child(2) {
 flex: 6;
 background-color: red;
}
https://codepen.io/thonly/pen/Jjrzgbv?editors=1100

Perfect! 🎉

If you’re a math whiz, you may have recognized that these fractions can be reduced by a Greatest Common Factor of 2:

section:first-child {
 flex: 1;
 background-color: yellow;
}
section:nth-child(2) {
 flex: 3;
 background-color: red;
}
section:last-child {
 flex: 1;
 background-color: purple;
}

In other words, we could have chosen to cut up our pizza into 5 equal slices if we had wanted. Either way, the children get the exact same amount in the final analysis.

Overall, this layout is quite easy to create, right?

Believe it or not, this Holy Grail was once infamously difficult to achieve without hacking away at the HTML and CSS code beyond recognition. Hence, its aptly dubbed name!

With Flexbox as we have witnessed, this once elusive layout is now quite trivial to attain! 😎

The finished Codepen:

In the next lecture, we will attempt to create four subsections but spread over 2 rows AND 2 columns.

Can Flexbox handle this 2-by-2 matrix? Let’s find out!

Flexbox versus Grid

Using Flexbox, let’s try to create 4 boxes spread over 2 rows and 2 columns inside of main:

<html>
 <head></head>
 <body>
  <header></header>
  <main>
   
  </main>
  <footer></footer>
 </body>
</html>

Like before, let’s create a section element for each box:

<html>
 <head></head>
 <body>
  <header></header>
  <main>
   <section></section>
   <section></section>
   <section></section>
   <section></section>
  </main>
  <footer></footer>
 </body>
</html>

To make these boxes behave as flexboxes, we set the display to flex in the parent:

main {
 flex: 7;
 border: 5px dashed orange;
 display: flex;
}

And the flex-flow to row and wrap to make the boxes wrap to the next row:

main {
 flex: 7;
 border: 5px dashed orange;
 display: flex;
 flex-flow: row wrap;
}

As for the children of main:

section {
}

Let’s give them all a flex property of 1 for grow, 1 for shrink, and 200px for the basis to make space for some boxes to wrap to the next row:

section {
 flex: 1 1 200px;
}

Again, if these flex properties are still confusing, they will be covered in great detail in Unit 3.

Finally, let’s give them all a border of 1px, solid and black so we can visualize them:

section {
 flex: 1 1 200px;
 border: 1px solid black;
}

It looks like we have achieved the 2x2 matrix that we wanted:

https://codepen.io/thonly/pen/bGoJOEP?editors=1100

However, there is a limitation.

Now try making the viewport wider:

As you can see, flex-wrap does not enforce the number of rows and columns.

In fact, Flexbox is intended to work really well whenever we want to lay out boxes in only one direction: rows OR columns

If we want to lay out boxes in two dimensions that respect both rows AND columns, we should use CSS Grid instead.

Let’s demonstrate by refactoring our code to use CSS Grid instead of Flexbox.

On our parent, instead of flex, let’s set the display to grid:

main {
 flex: 7;
 border: 5px dashed orange;
 display: grid;
}

Instead of flex-flow, we can use grid-template-rows to set the number of rows. Let’s create two rows and give them 1 fraction each:

main {
 flex: 7;
 border: 5px dashed orange;
 display: grid;
 grid-template-rows: 1fr 1fr;
}

To set the number of columns, we can use grid-template-columns. Let’s also create two columns and give them each 1fr:

main {
 flex: 7;
 border: 5px dashed orange;
 display: grid;
 grid-template-rows: 1fr 1fr;
 grid-template-columns: 1fr 1fr;
}

As for the children of main, the flex property is no longer necessary:

section {
 flex: 1 1 200px; // delete
 border: 1px solid black;
}

As you can see, CSS Grid uses fr units which behave exactly like the fraction units of Flexbox.

1fr = 1 fraction

The reason CSS Grid has the fr designation whereas Flexbox does not is because CSS Grid also allows other types of units too! (e.g., absolute units)

Now, let’s see what happens if we change the viewport size like before:

https://codepen.io/thonly/pen/qBmYOxa?editors=1100

As you can see, when we use CSS Grid, an invisible grid system is created that always respect the number of rows and columns.

The finished Codepen:

CSS Grid

Now that we know how useful a grid system can be, let’s study it in detail.

Firstly, if all the columns or rows have equal lengths, we can use the repeat() shortcut:

main {
 flex: 7;
 border: 5px dashed orange;
 display: grid;
 grid-template-columns: repeat();
 grid-template-rows: 1fr 1fr;
}

Then inside the parentheses, we indicate the number of times, and the length for each one:

main {
 flex: 7;
 border: 5px dashed orange;
 display: grid;
 grid-template-columns: repeat(2, 1fr);
 grid-template-rows: 1fr 1fr;
}

Likewise, for the rows:

main {
 flex: 7;
 border: 5px dashed orange;
 display: grid;
 grid-template-columns: repeat(2, 1fr);
 grid-template-rows: repeat(2, 1fr);
}

Using this shortcut, we can easily create a grid system with 12 columns and 12 rows for example:

main {
 flex: 7;
 border: 5px dashed orange;
 display: grid;
 grid-template-columns: repeat(12, 1fr);
 grid-template-rows: repeat(12, 1fr);
}

When we define grid-template-columns and grid-template-rows, we are defining an explicit grid system that has column lines and row lines.

For example, inside main, the column lines are 1, 2, and 3 (from left to right). And the row lines are 1, 2, and 3 (from top to bottom).

https://codepen.io/thonly/pen/qBmYOxa?editors=1100

To see the grid lines in Chrome, open Developer Tools and then click on the Layout tab and tick Grid overlays.

We can use these lines to place the children of main anywhere on this grid.

For example, let’s place the :first-child at:

  • grid-column: from line 2 to line 3
  • grid-row: from line 1 to line 2
section:first-child {
 grid-column: 2 / 3;
 grid-row: 1 / 2
}

To visualize it, let’s give it a background-color of yellow:

section:first-child {
 grid-column: 2 / 3;
 grid-row: 1 / 2;
 background-color: yellow;
}

If we want, we can even span it across two rows:

section:first-child {
 grid-column: 2 / 3;
 grid-row: 1 / 3;
 background-color: yellow;
}

Instead of specifying a row line, we can also simply write span 2:

section:first-child {
 grid-column: 2 / 3;
 grid-row: 1 / span 2;
 background-color: yellow;
}

If we prefer, there is another method we can use to place the children of main anywhere on our grid.

On the top row, let’s name the left box as area one and the right box as area two. On the bottom row, let’s name the left box as area three and the right box as area four.

Then, on the parent, we can define the grid-template-areas as:

  • “one two” for the top row
  • “three four” for the bottom row
main {
 flex: 7;
 border: 5px dashed orange;
 display: grid;
 grid-template-columns: repeat(2, 1fr);
 grid-template-rows: repeat(2, 1fr);
 grid-template-areas: 
  "one two"
  "three four";
}

With these areas defined, let’s try placing the :last-child at grid-area two:

section:last-child {
 grid-area: two;
}

To visualize it, let’s give it a background-color of violet:

section:last-child {
 grid-area: two;
 background-color: violet;
}

As you can see, this places the :last-child on top of the :first-child. The reason is because by default their stacking order follows their order in the HTML Tree.

HTML Tree Order => Stacking Order

If we want, we can change their stacking order by using the z-index which is 0 by default:

section:first-child {
 grid-column: 2 / 3;
 grid-row: 1 / span 2;
 background-color: yellow;
 z-index: 0;
}
section:last-child {
 grid-area: two;
 background-color: violet;
 z-index: 0;
}

If we want the :first-child to be on top, we simply give it a higher z-index.

For example: 1

section:first-child {
 grid-column: 2 / 3;
 grid-row: 1 / span 2;
 background-color: yellow;
 z-index: 1;
}
section:last-child {
 grid-area: two;
 background-color: violet;
 z-index: 0;
}

But let’s make the :last-child on top instead by giving it an even greater z-index: 2

section:first-child {
 grid-column: 2 / 3;
 grid-row: 1 / span 2;
 background-color: yellow;
 z-index: 1;
}
section:last-child {
 grid-area: two;
 background-color: violet;
 z-index: 2;
}

Moreover, if we want a grid system that is more flexible, we can define an implicit grid system by removing one dimension: grid-template-columns or grid-template-rows

For example, let’s remove grid-template-rows. In its place, we can define a grid-auto-flow and set it to row:

main {
 flex: 7;
 border: 5px dashed orange;
 display: grid;
 grid-template-columns: repeat(2, 1fr);
 grid-auto-flow: row;
 grid-template-areas: 
  "one two"
  "three four";
}

This makes the row behave like flex-wrap!

We can also specify a height for these automatic rows using grid-auto-rows.

For example: 100px

main {
 flex: 7;
 border: 5px dashed orange;
 display: grid;
 grid-template-columns: repeat(2, 1fr);
 grid-auto-flow: row;
 grid-auto-rows: 100px;
 grid-template-areas: 
  "one two"
  "three four";
}

Finally, in between the columns, we can specify a gap using grid-column-gap.

For example: 5px

main {
 flex: 7;
 border: 5px dashed orange;
 display: grid;
 grid-template-columns: repeat(2, 1fr);
 grid-auto-flow: row;
 grid-auto-rows: 100px;
 grid-column-gap: 5px; 
 grid-template-areas: 
  "one two"
  "three four";
}

Likewise, we can specify a gap between the rows as well using grid-row-gap.

For example: 10px

main {
 flex: 7;
 border: 5px dashed orange;
 display: grid;
 grid-template-columns: repeat(2, 1fr);
 grid-auto-flow: row;
 grid-auto-rows: 100px;
 grid-column-gap: 5px; 
 grid-row-gap: 10px;
 grid-template-areas: 
  "one two"
  "three four";
}
https://codepen.io/thonly/pen/qBmyaZN?editors=1100

The finished Codepen:

Summary

Flexbox is amazing when we want to align children elements along one axis. But if we want to align them along both axes, it is better to use CSS Grid to create an invisible grid system upon which we can place the children elements.

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout#the_implicit_and_explicit_grid

To create a grid system, we set the display to grid on the parent element.

main {
  display: grid;
}

Then, we can define the grid tracks using grid-template-rows and grid-template-columns.

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_grid_track.png

These tracks can be defined using any length units. If we want, we can also use fraction units which behave like flexboxes that expand to fill the parent container.

grid-template-columns: 1fr 1fr 1fr;

Like flexboxes, we can think of fr units as slices of a whole pizza. We are free to cut up the whole pizza into as many equal fractions as we desire.

If the track sizes are repetitive, we can use the repeat() shortcut:

grid-template-columns: repeat(3, 1fr);

When we define grid-template-columns and grid-template-rows, the tracks created are part of the explicit grid.

If one axis is not defined, its corresponding tracks may still be created as part of the implicit grid.

These implicit tracks can be controlled using:

  • grid-auto-flow
  • grid-auto-rows
  • grid-auto-columns

As such, they behave like flex-wrap.

The grid lines are numbered from left to right, and top to bottom:

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_diagram_numbered_grid_lines.png

This makes it possible to place children elements anywhere on the grid by using grid-column and grid-row.

We can place elements in any grid cell:

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_grid_cell.png

Or, we can span them across multiple cells:

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_grid_area.png

Gutters are the gaps in between the track rows and track columns.

To create them, we can use row-gap and column-gap.

column-gap: 10px;
row-gap: 1em;

Multiple elements can be placed on the same cell.

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout/1_nested_grids_in_flow.png

When this happens, the elements stack on top of one another according to their order in the HTML Tree.

To change this default order, we can use the z-index.

z-index: 2;

Don’t worry if CSS Grid is still confusing. We will study it some more in Unit 3!

Concept Quiz

Take my Programming Concept Quiz to check your understanding! For every correct choice, you will earn SW Coins which you can redeem for coupons towards the purchase of any of my Udemy courses!

Sample Quiz Questions for Lesson 15:

Question 1:

Which display type is best for aligning elements that respect both axes?

  1. inline-block
  2. block
  3. flex
  4. grid

Question 2:

Which grid property is NOT declared on the parent element?

  1. display
  2. grid-template-rows
  3. grid-template-columns
  4. grid-auto-flow
  5. grid-auto-rows
  6. grid-auto-columns
  7. z-index
  8. grid-row-gap
  9. grid-column-gap

Question 3:

Which grid property is NOT declared on the children elements?

  1. grid-column
  2. grid-row
  3. grid-area
  4. grid-template-areas

Question 4:

repeat(4, 2fr) is equal to:

  1. 1fr 1fr
  2. 2fr 2fr
  3. 2fr 2fr 2fr 2fr
  4. 1fr 1fr 1fr 1fr

Question 5:

Which grid property does NOT create an explicit grid?

  1. grid-template-rows
  2. grid-template-columns
  3. grid-auto-flow

Question 6:

Which grid property does NOT relate to the implicit grid?

  1. grid-auto-row
  2. grid-auto-columns
  3. grid-template-areas

Question 7:

Grid lines are numbered from:

  1. right to left, bottom to top
  2. left to right, bottom to top
  3. right to left, top to bottom
  4. left to right, top to bottom

Question 8:

We CANNOT span elements across multiple grid cells?

  1. True
  2. False

Question 9:

A lower z-index will make the element appear on the:

  1. bottom
  2. top

Question 10:

grid-auto-flow behaves like flex-wrap.

  1. True
  2. False

Question 11:

fr units behave like flexboxes.

  1. True
  2. False

Question 12:

Only direct children can be placed on the grid system created by the parent element.

  1. True
  2. False

Programming Concept Quiz for Chapter 15

Coding Exercises

Check out my Interactive Coding Exercises to put to practice what you have learned! There, you will also find interactive hints to help you understand each line of code. Likewise, for every correct solution, you will earn SW Coins which you can redeem for coupons towards the purchase of any of my Udemy courses!

Interactive Coding Exercises for Chapter 15

Syntax Flashcards

Review what you have learned by playing my Syntax Flashcard Game! These flashcards are designed to help you commit to memory all the new code syntaxes you learned in this lesson. Likewise, for every correct answer, you will earn SW Coins which you can redeem for coupons towards the purchase of any of my Udemy courses!

Syntax Flashcard Game for Chapter 15

Next Steps

Congrats on completing Unit 2: Lesson 10 of 13! 🎉

Unit 1: 100% Completed
Unit 2: 77% Completed
Unit 3: 0% Completed
Unit 4: 0% Completed
Unit 5: 0% Completed
Bonus Unit 6: 0% Completed
Bonus Unit 7: 0% Completed
Overall Progress: 15% Completed

Join Remote Frontend Cohort Program

Next Lesson

Since we can now effortless create any page layout of our choosing, we are ready to add actual content! In the next lesson, we will begin by learning how to add texts. Sounds simple enough on the surface, but we will also look under the surface. Believe it or not, plain texts are HTML elements too except they are just tag-less. On the DOM Tree, they exist as textNodes. In the next lesson, we will use JavaScript to help us study these textNodes in detail. Texts are so ubiquitous (especially on a platform like Medium) that they seem trivial, but nothing is further from the truth. Mastering textNodes will help us glimpse the incredible technology powering a writing platform like Medium!

Chapter 16: HTML Text Nodes in JavaScript

Table of Contents

When you use my referral link above 👆 to become a Medium member, all proceeds will be donated towards the construction of the Silicon Wat Campus for children in Ukraine and Cambodia ❤️

HTML
CSS
JavaScript
Front End Development
Programming
Recommended from ReadMedium