would be a necessity.\nAt 3 in the morning, when I was failing to get to sleep, my mind happened upon an question: \u201cCould you use calc?\u201d\nAt some point I drifted back to sleep so the next day I set upon seeing if this was possible. I knew that the maximum width of the central grid needed to be 1008px. The left and right columns needed to be however many pixels were left in the viewport divided by 2. In CSS it looked like I would need to use calc twice. The first time to takeaway 1008px from 100% of the viewport width and the second to divide that result by 2.\ncalc(calc(100% - 1008px) / 2)\nThe CSS above was part of the value that I would need to include in the declaration for the grid.\n.container {\n display: grid;\n grid-gap: .75em;\n grid-template-columns:\n [full-start]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [main-start]\n repeat(14, [col-start] 1fr)\n [main-end]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [full-end];\n}\nWe have created the grid required. A full-width grid, with a central 14 column grid, using fewer
elements.\n\nSee the Pen Design Systems and CSS Grid, 6 by Stuart Robson (@sturobson) on CodePen.\n\nSuccess!\nProgressive enhancement\nNow that we have created the grid system required we need to back-track a little.\nNot all browsers support Grid, over the last 9 months or so this has gotten a lot better. However there will still be browsers that visit that potentially won\u2019t have support. The effort required to make the grid system fall back for these browsers depends on your product or sites browser support.\n\nTo determine if we will be using Grid or not for a browser we will make use of feature queries. This would mean that any version of Internet Explorer will not get Grid, as well as some mobile browsers and older versions of other browsers.\n@supports (display: grid) {\n /* Styles for browsers that support Grid */\n}\nIf a browser does not pass the requirements for @supports we will fallback to using flexbox where possible, and if that is not supported we are happy for the page to be laid out in one column.\nA website doesn\u2019t have to look the same in every browser after all.\nA responsive grid\nWe started with the big picture, how the grid would be at a large viewport and the grid system we have created gets a little silly when the viewport gets smaller.\nAt smaller viewports we have a single column layout where every item of content, every component stacks atop each other. We don\u2019t start to define a grid before we the viewport gets to 700px wide. At this point we have an 8 column grid and if the viewport gets to 1100px or wider we have our 14 column grid.\n/*\n * to start with there is no 'grid' just a single column\n */\n.container {\n padding: 0 .75em;\n}\n\n/*\n * when we get to 700px we create an 8 column grid with\n * a left and right area to breakout of the grid.\n */\n@media (min-width: 700px) {\n .container {\n display: grid;\n grid-gap: .75em;\n grid-template-columns:\n [full-start]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [main-start]\n repeat(8, [col-start] 1fr)\n [main-end]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [full-end];\n padding: 0;\n }\n}\n\n/*\n * when we get to 1100px we create an 14 column grid with\n * a left and right area to breakout of the grid.\n */\n@media (min-width: 1100px) {\n .container {\n grid-template-columns:\n [full-start]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [main-start]\n repeat(14, [col-start] 1fr)\n [main-end]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [full-end];\n }\n}\nBeing explicit in creating this there is some repetition that we could avoid, we will define the number of columns for the inner grid by using a Sass variable or CSS custom properties (more commonly termed as CSS variables).\nLet\u2019s use CSS custom properties. We need to declare the variable first by adding it to our stylesheet.\n:root {\n --inner-grid-columns: 8;\n}\nWe then need to edit a few more lines. First make use of the variable for this line.\nrepeat(8, [col-start] 1fr)\n/* replace with */\nrepeat(var(--inner-grid-columns), [col-start] 1fr)\nThen at the 1100px breakpoint we would only need to change the value of the \u2014inner-grid-columns value.\n@media (min-width: 1100px) {\n .container {\n grid-template-columns:\n [full-start]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [main-start]\n repeat(14, [col-start] 1fr)\n [main-end]\n minmax(calc(calc(100% - 1008px) / 2), 1fr)\n [full-end];\n }\n}\n/* replace with */\n@media (min-width: 1100px) {\n .container {\n --inner-grid-columns: 14;\n }\n}\nSee the Pen Design Systems and CSS Grid, 8 by Stuart Robson (@sturobson) on CodePen.\n\nThe final grid system\nWe have finally created our new grid for the design system. It stays true to the existing grid in place, adds the ability to break-out of the grid, removes a
that could have been needed for the nested 14 column grid.\nWe can move on to the new component.\nCreating a new component\nBack to the new components we are needing to create.\n\nTo me there are two components one of which is a slight variant of the first. This component contains a title, subtitle, a paragraph (potentially paragraphs) of content, a list, and a call to action.\nTo start with we should write the HTML for the component, something like this:\n
\n \n \n \n \n \n\nTo place the component on the existing grid is fine, but as child elements are not affected by the container grid we need to define another grid for the features component.\nAs the grid doesn\u2019t get invoked until 700px it is possible to negate the need for a media query.\n.features {\n grid-column: col-start 1 / span 6;\n}\n\n@supports (display: grid) {\n @media (min-width: 1100px) {\n .features {\n grid-column-end: 9;\n }\n }\n}\nWe can also avoid duplication of declarations by making use of the grid-column shorthand and longhand. We need to write a little more CSS for the variant component, the one that will sit on the right side of the page too.\n.features:nth-of-type(even) {\n grid-column-start: 4;\n grid-row: 2;\n}\n\n@supports (display: grid) {\n @media (min-width: 1100px) {\n .features:nth-of-type(even) {\n grid-column-start: 9;\n grid-column-end: 16;\n }\n }\n}\nWe cannot place the items within features on the container grid as they are not direct children. To make this work we have to define a grid for the features component.\nWe can do this by defining the grid at the first breakpoint of 700px making use of CSS custom properties again to define how many columns there will need to be.\n.features {\n grid-column: col-start 1 / span 6;\n --features-grid-columns: 5;\n}\n\n@supports (display: grid) {\n @media (min-width: 700px) {\n .features {\n display: grid;\n grid-gap: .75em;\n grid-template-columns: repeat(var(--features-grid-columns), [col-start] 1fr);\n }\n }\n}\n\n@supports (display: grid) {\n @media (min-width: 1100px) {\n .features {\n grid-column-end: 9;\n --features-grid-columns: 7;\n }\n }\n}\nSee the Pen Design Systems and CSS Grid, 10 by Stuart Robson (@sturobson) on CodePen.\n\nLaying out the parts\nLooking at the spec and reading several articles I feel there are two ways that I could layout the text of this component on the grid.\nWe could use the grid-column shorthand that incorporates grid-column-start and grid-column-end or we can make use of grid-template-areas.\ngrid-template-areas allow for a nice visual way of representing how the parts of the component would be laid out. We can take the the mock of the features on the grid and represent them in text in our CSS.\n\nWithin the .features rule we can add the relevant grid-template-areas value to represent the above.\n.features {\n display: grid;\n grid-template-columns: repeat(var(--features-grid-columns), [col-start] 1fr);\n grid-template-areas:\n \". title title title title title title\"\n \". subtitle subtitle subtitle subtitle subtitle . \"\n \". content content content content . . \"\n \". list list list . . . \"\n \". . . . link link link \";\n}\n\nIn order to make the variant of the component we would have to create the grid-template-areas for that component too.\nWe then need to tell each element of the component in what grid-area it should be placed within the grid.\n.features__title { grid-area: title; }\n.features__subtitle { grid-area: subtitle; }\n.features__content { grid-area: content; }\n.features__list { grid-area: list; }\n.features__link { grid-area: link; }\nSee the Pen Design Systems and CSS Grid, 12 by Stuart Robson (@sturobson) on CodePen.\n\nThe other way would be to use the grid-column shorthand and the grid-column-start and grid-column-end we have used previously.\n.features .features__title {\n grid-column: col-start 2 / span 6;\n}\n.features .features__subtitle {\n grid-column: col-start 2 / span 5;\n}\n.features .features__content {\n grid-column: col-start 2 / span 4;\n}\n.features .features__list {\n grid-column: col-start 2 / span 4;\n}\n.features .features__link {\n grid-column: col-start 5 / span 3;\n}\nFor the variant of the component we can use the grid-column-start property as it will inherit the span defined in the grid-column shorthand.\n.features:nth-of-type(even) .features__title {\n grid-column-start: col-start 1;\n}\n.features:nth-of-type(even) .features__subtitle {\n grid-column-start: col-start 1;\n}\n.features:nth-of-type(even) .features__content {\n grid-column-start: col-start 3;\n}\n.features:nth-of-type(even) .features__list {\n grid-column-start: col-start 3;\n}\n.features:nth-of-type(even) .features__link {\n grid-column-start: col-start 1;\n}\nSee the Pen Design Systems and CSS Grid, 14 by Stuart Robson (@sturobson) on CodePen.\n\nI think, for now, we will go with using grid-column properties rather than grid-template-areas. The repetition needed for creating the variant feels too much where we can change the grid-column-start instead, keeping the components elements layout properties tied a little closer to the elements rather than the grid.\nSome additional decisions\nThe current component library has existing styles for titles, subtitles, lists, paragraphs of text and calls to action. These are name-spaced so that they shouldn\u2019t clash with any other components. Looking forward there will be a chance that other products adopt the component library, but they may bring their own styles for titles, subtitles, etc.\nOne way that we could write our code now for that near future possibility is to make sure our classes are working hard. Using class-attribute selectors we can target part of the class attributes that we know the elements in the component will have using *=.\n.features [class*=\"title\"] {\n grid-column: col-start 2 / span 6;\n}\n.features [class*=\"subtitle\"] {\n grid-column: col-start 2 / span 5;\n}\n.features [class*=\"content\"] {\n grid-column: col-start 2 / span 4;\n}\n.features [class*=\"list\"] {\n grid-column: col-start 2 / span 4;\n}\n.features [class*=\"link\"] {\n grid-column: col-start 5 / span 3;\n}\nSee the Pen Design Systems and CSS Grid, 15 by Stuart Robson (@sturobson) on CodePen.\n\nAlthough the component we have created have a title, subtitle, paragraphs, a list, and a call to action there may be a time where one ore more of these is not required or available. One thing I found out is that if the element doesn\u2019t exist then grid will not create space for it. This may be obvious, but it can be really helpful in making a nice malleable component.\nWe have only looked at columns, as existing components have their own spacing for the vertical rhythm of the page we don\u2019t really want to have them take up equal space in the component and just take up the space as needed. We can do this by adding grid-auto-rows: min-content; to our .features. This is useful if you also need your component to take up a height that is more than the component itself.\nThe grid of the future\nFrom prototyping this new grid and components in CSS Grid, I\u2019ve found it a fantastic way to reimagine how we can create a layout or grid system for our sites. It gives us options to create the same layouts in differing ways that could suit a project and its needs.\nIt allows us to carry on \u2013 if we choose to \u2013 using a
-based grid but swapping out floats for CSS Grid or to tie it to our components so they have specific places to go depending on what component is being used. Or we could have several \u2018grid components\u2019 in our design system that we could use to layout various components throughout a page.\nIf you find yourself tasked with creating some new components for your design system try it. If you are starting from scratch I believe you really should start with CSS Grid for your layout.\nIt really feels like the possibilities are endless in terms of layout for the web.\nResources\nHere are just a few resources I have pawed over these last few weeks whilst getting acquainted with CSS Grid.\n\nA collection of CodePens from this article\nGrid by Example from Rachel Andrew\nA Complete Guide to CSS Grid on Codrops from Hui Jing Chen\nRachel Andrew\u2019s Blog Archive tagged: cssgrid\nCSS Grid Layout Examples\nMDN\u2019s CSS Grid Layout\nA Complete Guide to Grid from CSS-Tricks\nCSS Grid Layout Module Level 1 Specification", "year": "2017", "author": "Stuart Robson", "author_slug": "stuartrobson", "published": "2017-12-12T00:00:00+00:00", "url": "https://24ways.org/2017/design-systems-and-css-grid/", "topic": "code"}