<div class="u-wrapper"> <div class="row"> <div class="u-width--full"> <h1>CSS Grid with variables</h1> <p> <strong>Short version:</strong> Instead of precompiling math for our grids we can do it live in the browser using CSS variables, thus saving us a LOT of lines in CSS (...in the future. I'm looking at you Explorer) </p> </div> </div> <div class="row"> <div class="u-width--full"> <p>Here are two elements, lets pretend they're a sidebar and an article element</p> </div> <div class="u-width sidebar"> <div class="demo"></div> </div> <div class="u-width content"> <div class="demo"></div> </div> <div class="u-width--full"> <p>No grid classes classes like <code>col-2</code> or <code>grid-12_lg-8_md-6_sm-4_xs-2</code>. Instead we're using <strong>a variable on each element.</strong> Here's whats going on:</p> </div> </div> <div class="row"> <div class="u-width--full"> <p> First off we need to define number of columns and the width of our grid gutters. </p> <pre> :root{ --column: 8; --gutters: 10; } </pre> <p> For our own sanity we'll use flexbox. </p> <pre> .row{ display: flex; flex-wrap: wrap; margin: 0 calc(var(--gutter) * -1px) ; } </pre> <p> Flex defaults to 100% width, same as display: block. The negative margins works kind of like calc(100% + 20px) in addition to margin-left: -10px. Just neater. They're crucial to helps us offset the gutters coming from the columns. </p> <h3> The magic ensues. </h3> <p>We'll make a wildcard selector for our necessary helper class. On its own it doesn't really do much.</p> <pre> [class*="u-width"]{ padding-right: calc(var(--gutter) * 1px); padding-left: calc(var(--gutter) * 1px); flex-basis: calc((100% / var(--columns)) * var(--width)); } </pre> <p> This selector will kinda work as a function for the most part. Padding for gutters and flex-basis for width. The interesting part here is --width. Because of this variable we can set it on any element that matches our wildcard selector. An example: </p> <pre> <div class="u-width sidebar"> ... </div> </pre> <p> If we needed sidebar to be 2 columns wide we can do it simply by: </p> <pre> .sidebar{ --width: 2; } .content { --width: 4; } </pre> <p> This works because variables in CSS are inherited and can be used as a scope. In other words, we just passed the --width to the u-width selector and calc takes care of the rest. Boom. Mic dropped. 14 lines of future vanilla CSS. </p> <p> In addtion, you could extend this to be more like any other stand alone grid, but still with a lot less markup. </p> </div> </div> <div class="row"> <div class="u-width--full"> <h3>Extending the Grid</h3> </div> <div class="u-width m--2 l--4"> <div class="demo"></div> </div> <div class="u-width m--2"> <div class="demo"></div> </div> <div class="u-width m--2"> <div class="demo"></div> </div> <div class="u-width m--2"> <div class="demo"></div> </div> <div class="u-width m--4 l--2"> <div class="demo"></div> </div> <div class="u-width m--4 l--4"> <div class="demo"></div> </div> <div class="u-width m--6"> <div class="demo"></div> </div> <div class="u-width m--2"> <div class="demo"></div> </div> <div class="u-width--full"> <p>Here we've got a few elements with classes that define their width. I've used <code> <div class="u-width m--4 l--4"> ... </div> </code>, but it's really up to you. This is how they're setup: </p> <pre> .m--2{ --width: 2; } .m--4{ --width: 4; } .m--6{ --width: 6; } .l--2{ --width: 2; } .l--4{ --width: 4; } .l--6{ --width: 6; } /* media query are implied */ </pre> <p>And that's it really.</p> </div> </div> </div>

!